I am struggling with the Lasagna exercise

Thanks for your thoughts @SleeplessByte, @iHiD. I will first respond to the more generic points by Jeremy, and then (perhaps later or tomorrow) address the very specific and interesting points by @SleeplessByte

I think you will agree that it is a fluid scale, from newbies to seasoned developers. I know you have sometimes make a choice, but I think it would be great to cater for as wide spectrum as possible, when feasible. That student of mine… well, I’ll be helping a little and I’m sure she will get a lot out of exercism as many others do. That’s not the point. I was inspired by the long thread with a number of people complaining about the problems with the exercise so wanted to contribute some ideas.

The point is, that I think that using concepts like content design, information architecture, or perhaps accessibility more could make what is already a great resource into something fantastic! Simple things like order of tests (from my other post), or offloading unnecessary but interesting information somewhere else can broaden the appeal and usability of a track.

I will follow more thoroughly with answers to the specific challenges above, but let’s look at one. “If you come from a language that is strongly typed, you will absolutely require the information that this Python is dynamically typed.”. Fair enough. However there are different ways to convey that knowledge. We can lead the instructions with

Python is a dynamic and strongly typed object-oriented programming language. It employs both duck typing and gradual typing, via type hints.

Or we could start with something else, and then slip something like this in

In Python you don’t have to worry about types (but you can read about types in Python if you would like to know more).

Both of those phrases have enough information for both an expert and a novice with an added benefit that both of them can easily get the gist of what it is.

In fact it might be easier for the experienced person who already read a lot about the language and would just like to practice.

Jeremy, you make a very valid point that perhaps the maintainers considered it and made a decision that it is essential. We don’t know, but wouldn’t it be great, and wouldn’t it help the longer term plan of reducing load of maintainers, if decisions like that were documented and publicly available? And maybe they are, and I don’t know where to look.

Still, I hope you don’t mind me attempting a constructive critique here on the forum. (I’ll keep my uncritically positive thoughts to twitter and such like ;) )

Totally understandable. I’d say the majority of the people who post on the forum struggling with a Lasagna or similar “basics” exercise are relatively new to programming though, so actively not the people the exercise is written for. (Bare in mind thousands of people a day sign up to Exercism and many more use it daily, so the frustration is good to consider in that context also. But equally, I appreciate it takes a brave few to complain and that most will just silently leave!)

It would. But there’s already an overwhelming workload for maintainers trying to just build tracks in their spare time, and them documenting specific decisions adds even more work (and generally even more un-fun work) which burns them out further.

There is lots of documentation on how Concept Exercises should be written etc (e.g. here and here, and where there are org-wide decisions that we can make to make these things clearer for maintainers, that’d be great, but Exercism doesn’t (and can’t tangibly) work on any basis other than these decisions being delegated to maintainers who have to use their own judgement to make them.

I personally really like that initial sentence, as it conveys to me the mindset to approach the language with right away. But also I could entirely see how it could be reworded to be more accessible via the method you suggest. However, I still think that the whole exercise will either be overwhelming or not depending on your experience as a developer. For someone who can code, I don’t think the existing sentence is overly scary. For someone who can’t the whole thing will be scary.

But yes, maybe we can remove anything that’s not needed for this exercise and introduce it further on instead. I wrote the Ruby lasagna introduction, which is a bit more minimal than Python’s - maybe that’s more aligned to your thinking?

Not at all. And I appreciate the tone in which you’re going about it.

All I’d say is that the people building these exercises have spent thousands of hours discussing, debating and considering all these things over the last few years, and are in a constant state of having to compromise for many different perspectives and opinions. My job is to provide the best possible guide-rails for maintainers and then trust them to do the best job they can and help protect them from becoming overwhelmed and exhausted by the vast amount of feedback they receive. The reason we paused community contributions was that these discussions take huge amounts of maintainers time to resolve often only a paragraph here or there, which mean that much more substantial changes to the site (and often the stuff maintainers enjoy working on) don’t get done.

You’d be amazed at how much feedback we get the other way moaning that these documents are way too simply written and should be compressed to be more technical. It’s hard.

I know given the time, the Python maintainers would love to go through and work even more on every exercise, but there’s also a mass of other work that would make a huge difference too. Bethany and others have spent dozens, if not hundreds, of hours working on this exercise alone, and I imagine are sick to the sight of it at this stage :grin: And maybe this exercise is special, as it’s the first one and so the one that most people will need a good onramp via, and it’s also the one that gets the most feedback as a result.


The final thing I’d say is that tangible examples help. Suggestions to rewrite X as Y (with the logic provided as you’ve done) are infinitely more useful than just “this could be better” style comments. So I think the more tangible suggestions you can make, the better, as often those are liberating for maintainers who can look at something and be like “YES, that’s better. Thank you!” rather than feeling “Urgh, I know it’s not perfect, but it’s the best I’ve got capacity for” when only provided with general feedback. The tangible suggestions on the other thread about input-testing are a perfect example of this and meant that I immediately responded to that post with a real sense of positivity, rather than frustration. So I just want to reenforce that as a final note.


Everyone: I’m having the weekend off now. Play nice, folks! :slight_smile:

3 Likes

Yes please. I rather have ten more of your posts than not. I meant it when I said “take it at face value”, as everything else in my post is without any frustration or emotion towards you.


I wanted to respond to this right now, and I’ll look into a more contentful response later (as I’m doing a “deploy of death” on friday night aaaaah).

1 Like

Hi community, I am new to Python but I’ve done the same challenge in “Go”.

The first task is to declare a constant and I did it like this:

```EXPECTED_BAKED_TIME = 40````

And I’m getting:

 ImportError while importing test module '.mnt.exercism-iteration.lasagna_test.py'.
Hint: make sure your test modules.packages have valid Python names.
Traceback:
.mnt.exercism-iteration.lasagna_test.py:6: in <module>
    from lasagna import (EXPECTED_BAKE_TIME,
E   ImportError: cannot import name 'EXPECTED_BAKE_TIME' from 'lasagna' (.mnt.exercism-iteration.lasagna.py)

During handling of the above exception, another exception occurred:
.usr.local.lib.python3.10.importlib.__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
.mnt.exercism-iteration.lasagna_test.py:23: in <module>
    raise ImportError("In your 'lasagna.py' file, we can not find or import the"
E   ImportError: In your 'lasagna.py' file, we can not find or import the function named 'EXPECTED_BAKE_TIME()'. Did you mis-name or forget to define it?

Can you help me understand what am I doing wrong?

You have BAKED instead of BAKE

Good catch!

But unfortunately, fixing does not solve the problem.

I think the main issue is the:
ImportError: cannot import name 'EXPECTED_BAKE_TIME' from 'lasagna' (.mnt.exercism-iteration.lasagna.py)

Can you share your entire code? Or, better yet, if you use the CLI, you can use the Exercism command to submit your code for mentoring!

Thanks! I did and they help me :wink:

1 Like

Hi @gonzaloalonsofiks!

That stack trace text (sadly) is a bug.

It’s fixed in this PR (Test Runner #110) and this PR (Content #3339), but they’ve been waiting on review and approval to merge.

What the message is trying to tell you on the last two lines (and it will be clearer after the fix to the error text!) is that the test runner is trying to import both constant names and function names in order to runt the tests on them. You’ve provided the constant name, but you (I am guessing) have not yet filled in the two function names described in tasks 3 and 4.

Once you do that, the ImportError will go away, and the tests will start passing or failing. :smile:

Python stack traces can look really intimidating at first, and can be confusing to read if you are not familiar with them (it doesn’t help here that we’ve screwed up the error message).

The easiest thing is to start at the very bottom, with the last line. Almost always, that’s the error that triggered everything else. From there, you can read “up” the stack to see what other havoc was caused – but the last line of a stack trace is most often the source of the problem.

Let me know if any of that helps, and if you have any additional questions or issues. :smile:

Hi @BethanyG!

Thanks for being so clear on this. Once I passed the fear of the first lines, I decided to continue with the code and then when I tested it was (pretty much) working.

I was able to fix it and finish the exercise! :heart_hands:

I have approved both, but I think my “approval” powers have diminished in one and I never had that power in the other.

Hello again. I had to focus on few other things outside of Exercism over the last week, but whenever I had a moment I kept looking at the Lasagna exercises to build a better picture of the “problem”. I have now done this exercise in 10 languages on 10 tracks including Python, Ruby and JavaScrip as all were brought as examples above.

I now know what I like and what I don’t, exactly, but that’s just my opinion. I’d love to be able to do some “proper” user research into this, but for now here is what I think:

The Lasagna exercise is a very special case. In all tracks I have explored it comes right after the Hello World, and so, it is the first exercise where we have do anything more than change Goodbye, Mars! to Hello, World!. It is where we first actively engage with a new language on Exercism. We come to this point with varying levels of knowledge of the language and experience of programming, but with a shared desire (in my opinion) to try something new. And so, I think the exercise should be a small step in complexity and effort (reading can be an effort) to get to that dopamine hit - yes, I’ve done it! And it works! And I have learnt something new… what’s next?

Is reading difficult? Does it have to be? I argued above how we could change wording to make it more inclusive and perhaps appealing to wider range of experience. As it happened since I wrote it I ended up in a meeting of British Computer Society Digital Divide Specialist Group. It reminded me that there is so much more to it and to inclusivity in general. So much discussion about programming is in English, but for so many of us English is not our first language. The accidental complexity quickly piles on top of the essential complexity of the exercise.

And I know we can get through it. We are all here, discussing the finer details. But there is, in my opinion, great value of lowering the barrier of entry to allow others, with different backgrounds, with different personal circumstances to learn, to contribute to software.

We should also remember that learning a new programming language is to some extent similar to learning foreign languages. Learning 5th, 10th is easy. But the second? Those who tried learning a second language as adults will know how difficult it is to figure out what’s important and what is just “nice to have” and how important it is to start using it rather than read about it.

OK, enough of the philosophy. What could we do to the Lasagna exercise in practice to make better act as the step after the Hello World?

  1. Reduce in code comments to bare minimum, to show how comments look like, to guide the implementation a little, but not to be a block of text with every possible feature of doc strings. Personally I find Elixir version of the exercise far less intimidating than
  2. Reduce the introduction text. Python version has almost 300 lines of text (with very good information). Ruby
    only 20% of that with just under 60. I think there is value with basic information at this stage, but there is also value in getting people to do the exercise quickly and getting them to that feeling of “I can do it!”

Now, to the specific I promised to answer @SleeplessByte

You provided a relatively long list of “must know” things depending of where we come from. I think some of this information is already captured in the track info. Most languages have good Wikiipedia pages and a lot of resources online to which the introduction could link. But in the end I think it comes down how the information is presented and what is in the focus. Currently the Python track reads in a very encyclopaedic way. This allows a knowledgable person learn more and gather more information, but it doesn’t necessary allow for quick progress. I would suggest more outcome based description of the same topics.

Examples - the introduction

Python is a dynamic and strongly typed object-oriented programming language. It employs both duck typing and gradual typing, via type hints. Imperative, declarative (e.g., functional), and object-oriented programming styles are all supported, but internally everything in Python is an object.

This concept introduces 4 major Python language features: Name Assignment (variables and constants), Functions (and the return keyword), Comments, and Docstrings.

I would change this to

In this exercise you will explore 4 features of Python: name assignments of both variables and constants, functions with their input and returns, comments and docstring.

Then in the section about assignments and re-assignments we have

In Python, there are no keywords to define variables or constants. Both are names that help programmers reference values (objects) in a program and are written differently only by convention. On Exercism, variables are always written in snake_case, and constants in SCREAMING_SNAKE_CASE.

Names are assigned to values using =, or the assignment operator (<name> = <value>). A name (variable or constant) can be re-assigned over its lifetime to different values/object types.

I would try something like this instead

In Python we can reference values with programmer defined names (variables or constants).

To define a variable you may write number_of_chefs = 5 where number_of_chefs is the variable name in snake_case, = is the assignment operator and 5 is the value. From now one number_of_chefs refers to value 5 until you change it by another assignment, for example number_of_chefs = 6.

Constants, in Python, are variables which are not meant to be re-assigned with a different value and so always should have the same constant value. To show that intent we write them in SCREAMING_SNAKE_CASE.

If you tried some other languages before you might notice that in Python you don’t have to declare variable types or use any keywords to declare variables.
I think both variants of the text convey the same message but the second one might be more actionable and more approachable.

There is a 7,000 character limit to the comments here. Who knew! So continuing…

Once again, the above are just my opinions. I wish we could do user research to find out what works best for majority of people. I look at it from my perspective. I think Exercism can be a great tool to help make programming much more accessible than it is right now and change how we see literacy. A century reading and writing were might have still been seen as a special skill, one that could get you a well paid job. Today programming is seen as one too, but I do think that in the next few decades it will be an essential literacy skill to interact with increasingly digitalised world as writing is right now.

What I don’t know is what types of users are most numerous on Exercism, how much experience they have and what are their objectives so the above opinion might be completely misplaced.

As I was thinking about the “problem” and looking at all those Lasagna problems, not only I got hungry, but I had a few more ideas which I wanted to put out there (here?)

@SleeplessByte listed above a number of concerns that might be important moving between languages. There is a finite (although growing) number of concepts in programming. Programming languages effectively pick and mix more than innovate. And so, it should be possible to come out with a list of characteristics and concepts with brief description, perhaps with a series of links to good resources, explainers.

With that a few things could be possible.

  1. Generate personalised pages explaining moves between languages. The user could indicate (or we could know from what they have done on Exercism) what langauges they already know and they could be shown concisely the differences in the target language. Typing, block identification, comments, mutability. Things like that.

  2. At the top of exercises, and intro to intro sort of thing, we could have a list of concepts necessary to complete the exercise. A bullet point list to the explanations in general, and specifically in the language. Advantage of this would be that the introduction would be shorter for those who don’t need too much hand-holding, or who just want to give it a go. At the same time the general concepts could be shared between languages and so there would be less text to write over all. It would also allow better user experience if they don’t follow the exact path intended by the track designer.

  3. The above could be improved by tracking what concepts the users already tried not only in this but also in other languages and indicate that to them. Those covered could be either hidden from the list - the list could be renamed to ‘concepts you will learn’. Or the full list could be shown to indicate how much they already know.

  4. Concepts… the name is already used for groupings of tasks. I’m struggling with to find a word that would mean individual building blocks of programming. Things like variable, constant, assignment, operator, prefix notation, infix notation, class, function, invocation, binding… and so on.

Wouldn’t it be good addition to the gamification of user experience to somehow track and show users what they already know across languages and how easily they can move from one to another?

I know the above might be a lot of work and not something important at the current stage of Exercism development… but here they are for you to ignore :smiley:

1 Like

Hi there, I seem to be having a problem passing the test for task 5 as I seem to keep getting an error. Is there a problem with my code below?

"""Functions used in preparing Guido's gorgeous lasagna.

Learn about Guido, the creator of the Python language:
https://en.wikipedia.org/wiki/Guido_van_Rossum

This is a module docstring, used to describe the functionality
of a module and its functions and/or classes.
"""


#TODO: define the 'EXPECTED_BAKE_TIME' constant.
import lasagna
lasagna.EXPECTED_BAKE_TIME = 40

#TODO: Remove 'pass' and complete the 'bake_time_remaining()' function below.
def bake_time_remaining(remaining_time):
    """Calculate the bake time remaining.

    :param elapsed_bake_time: int - baking time already elapsed.
    :return: int - remaining bake time (in minutes) derived from 'EXPECTED_BAKE_TIME'.

    Function that takes the actual minutes the lasagna has been in the oven as
    an argument and returns how many minutes the lasagna still needs to bake
    based on the `EXPECTED_BAKE_TIME`.
    """
    bake_time_remaining = lasagna.EXPECTED_BAKE_TIME - remaining_time
    return bake_time_remaining

#TODO: Define the 'preparation_time_in_minutes()' function below.
# You might also consider using 'PREPARATION_TIME' here, if you have it defined.
def preparation_time_in_minutes(number_of_layers):
    preparation_time_in_minutes = number_of_layers * 2
    return preparation_time_in_minutes


#TODO: define the 'elapsed_time_in_minutes()' function below.
# Remember to add a docstring (you can copy and then alter the one from bake_time_remaining.)
def elapsed_time_in_minutes(number_of_layers,elapsed_bake_time):
    """Return the elapsed cooking time. 
    This function takes two integers representing the number of lasagna layers and the time already spent baking and calculates the total elapsed minutes spent cooking the lasagna. 
    """
    elapsed_time_in_minutes = (number_of_layers*2) + elapsed_bake_time
    return elapsed_time_in_minutes


What error are you getting?

The error message that I seem to be getting is that one of the variations of the test had failed. It expected a docstring but mentioned that it received none instead. Did I fail to classify the docstring?

Your preparation_time_in_minutes function is missing a docstring. Try adding:

"""Calculate the preparation time.""" 

Indented, just below the function definition, like this:

def preparation_time_in_minutes(number_of_layers):
    """Calculate the preparation time."""        

Ah I see. Can’t believe I missed out on that. Thank you!

1 Like

2 posts were split to a new topic: Stuggling to understand what the code means in Lasagna