Threads for priime0

    1. 30

      I’d also like to reference one of Felleisen’s earlier posts, Developing Developers, which also rationalizes what a pedagogical computer science curriculum should look like.

      Why does Northeastern use the Racket Student Languages in the intro course as opposed to Python? If the fundamentals are language-independent, then surely there’s no problem using Python? Felleisen addresses this by referencing the trinity. Beginners will have the best experience in an introductory course when:

      • The course has an emphasis on systematic design – an intentional method of analyzing and dissecting problems that builds on what they know.
      • A well-scoped language that is simple – readable error messages, low cognitive overhead, and accommodating of student’s growth.
      • A pedagogic IDE – tooling built specifically for beginners, including a simpler debugger and interactive environment.

      A transition to Python likely doesn’t fully satisfy the trinity, since it’s a complex, full-fledged programming language with several quirks and footguns for beginners. Likewise, Racket itself doesn’t pose a suitable alternative, since it’s also a complex, full-fledged programming language: that’s why students start with the Racket student languages instead! With the Racket student languages, they learn the entirety of that language before introducing new features and greater complexity. In particular, new features are integrated into the design recipe, a vehicle for teaching systematic design. Rather than teaching language features independently, problems are posed and these features are introduced as solutions and described from the context of the design recipe. You’d probably want to skim HtDP to see how they do this well.

      A language that could be an adequate substitution is Pyret, and it might be used in the new curriculum. One of the Pyret developers/researchers is @shriram, who had Felleisen as an advisor. The DCIC book, however, makes different decisions on the order in which to introduce ideas.

      On another note, the curriculum change likely isn’t because of dissatisfaction with the current curriculum. Rather, it’s political. I have a brief set of notes that describes this problem:

      • Part of Northeastern’s business is real-estate and acquiring satellite campuses.
      • Northeastern is legally required to send students to those satellite campuses.
      • The satellite campuses retain their existing professors.
      • The satellite campus professors are unwilling to learn the Fundies curriculum.
      • Since the satellite campus professors are unwilling to learn the Fundies curriculum, they don’t teach it to the students who attend the satellite campuses.
      • So, students who come from satellite campuses have a different experience – we believe this experience to be of lesser value.
      • We don’t want students to be advantaged/disadvantaged based on the campus they attend during their first year.
      • So, we either
        • find a way to teach the Fundies curriculum in the satellite campuses – but this has been attempted before unsuccessfully and is unlikely to work
        • change the Fundies curriculum to something the satellite campus professors do want to teach
      • The Khoury administration has decided to go with the latter.

      Second part: co-op.

      • OOD (third course in the sequence, “fundies 3”) is a requirement to go on co-op
      • Many students fail/withdraw from OOD
      • Consequently, many students can’t go on co-op and even drop out of CS
      • Khoury admin believes that is a problem – students are customers
      • Co-op placements are also low – students aren’t appealing enough to employers
      • Khoury admin believes that learning “modern”, industry-relevant skills would make students more employable
      • Thus, Khoury admin believes they should teach those skills

      Another implicit consequence is that downstream courses outside of the core curriculum will have to change. A classic programming languages course, taught by Eli Barzilay, will inevitably stop being taught the way it is. That course uses a new language based on Typed Racket for each homework, including one that emulates the lambda calculus! Barzilay has expressed that he will likely stop teaching the course if the curriculum changes, since it would be too time-consuming to teach basic Typed Racket to be productive enough for the rest of the course. Another course at Northeastern, Logic & Computation, also built a teaching language using Racket to teach the fundamentals of formal methods. There’s exciting courses such as Hack Your Own Language that teach how to build DSLs from Racket. It’s a shame some of these will have to change or cease being taught.

      I’m fairly involved in the Racket community. I have no qualms about transitioning away from the HtDP curriculum or from the Racket student languages. My concern is that the new curriculum does not adequately substitute for the old one, and instead will breed a new generation of AI-reliant code monkeys – to put it one way. The political pressure to switch curriculums is worrying, but I’m hoping some of the involved professors help steer the new proposed changes in the right direction.

      1. 6

        From my understanding, Rhombus (a Racket language) uses a bicameral syntax: shrubbery notation. There’s a paper “Rhombus: A New Spin on Macros without All the Parentheses” that goes deeper into shrubbery representation, which is produced from the reader phase in place of S-expressions. In other words, shrubbery notation aims to be “an extremely useful intermediate data structure” that is ready for some following parsing pass that can also handle macros.

        1. 6

          Correct, Shrubbery notation is designed to enable Rhombus to be bicameral.

          1. 3

            Funny, I would have guessed that shrubbery notation was related to Python. ;-)

          2. 20
            1. 6

              Pyret is great. It’s a “teaching language” made by some of the folks behind Racket, namely Shriram Krishnamurthi.

              1. 8

                For those interested in reading more, Pyret is used in A Data-Centric Introduction to Computing, oriented for beginners to programming (similar to How to Design Programs). Shriram Krishnamurthi’s recent research focuses on computer science pedagogy, and he wrote and used DCIC for the accelerated introduction to the CS section of Brown University, CS19.

                From my understanding, Tables in Pyret were included because of their relevance in the real world. It also has integration with Google Sheets. I think tables enable beginners to reason about problems using structures they’re already somewhat familiar with.

                1. 7

                  Another link from the same people is their paper on Types for Tables, which digs into how well existing type systems do or don’t work for typing first-class tables within a programming language.

                1. 2

                  Just came to thank you again. Cell is exactly what I was looking for, I’m very grateful for helping me find it. Much appreciated!

                2. 6

                  til logict, enjoyed reading this post.

                  sinilarly, ive been trying to grok logic programming by writing a meal planner given the state of my fridge, with racklog.

                  1. 2

                    You might also want to consider using the Racket miniKanren implementation (there’s also faster-minikanren).

                    I’ve enjoyed the brief amount of logic programming I’ve done in Racket.

                    1. 4

                      I had the privilege of reading the online version for free several years ago. This year, I decided to pay it back by purchasing the physical textbook, and I occasionally continue to reference it.

                      While I don’t currently work in the PL field, I find what I’ve learned to be useful (both from Crafting Interpreters and my university lectures). To be fair, I do interact with and contribute to an internal DSL at my current workplace, and also experiment with writing small compilers in my free time.

                    2. 10

                      Absolutely. This is also a great attitude to have in general. Understand how objects around you work, taking things apart, see how it can implemented in different ways and what are the tradeoffs. The knowledge and experience you gain will yield compounded benefits and likely come handy down the line many times over, often unexpectedly.

                      I’m always in disbelief when I see people discouraging experimentation, which seems to be a prevalent trait in the software industry for some reason. Now that I think about it, it might be because side projects here are more visible and publicly advertised as a side effect of FOSS culture? while other industries you only hear about them if you’re a close friend, especially at early stages, so the environment tends to be more supportive in comparison.

                      1. 14

                        I’m always in disbelief when I see people discouraging experimentation, which seems to be a prevalent trait in the software industry for some reason.

                        It kills me when I see people respond to a language announcement by complaining that there are too many languages. Most languages aren’t going to become common so it’s really not a big deal if people make something new. Just let people have some fun!

                        1. 20

                          This also leads to programming language creators feeling like they have to justify creating a new language. I’ve seen it on introductions to languages where the creator explicitly answers the question, “Why Another Programming Language?”.

                          It’s like saying, “There is already plenty of music, why write a new song?”.

                          1. 4

                            It’s a classic misconception of “not reinventing the wheel.”

                          2. 5

                            I’m working on my own lisp interpreter. Along the way I came up with a seemingly novel way to embed arbitrary data into ELF files and have the kernel load it automatically. Wrote a blog post about it to explain the implementation details, and showed off my language a little bit by demonstrating how I can use it to embed arbitrary code into the interpreter and have it become a self-contained application. It was shared here, and the top comment just expressed surprise at the fact someone had made yet another lisp. Someone replied “but it’s so fun”.

                            I really am having lots of fun. I feel like this is the project of a lifetime for me, it’s the kind of thing I’ve always wanted to make all along. I basically want to remake all of Linux user space in my image. I probably won’t make it, I’m just one guy. There is no doubt that it’s fun though. I definitely encourage everyone to try it.

                            1. 2

                              It depends a lot on the point of the new language. There are two good reasons for creating a new language:

                              • It’s fun, and you want to either enjoy yourself, learn something, or both.
                              • You have a novel idea for how to do programming better and your language is there to showcase these ideas.

                              Some people will object to the first one, but (I hope) not that many. The entire esoteric languages community is building things in this space.

                              The problem with a lot of new-language announcements is that they’re presented as if they’re the second, but they’re not actually either. It’s a slightly new syntax on old ideas, which is fine as a thing that you do for fun, but the announcement is trying to get people to use the language.

                              1. 2

                                I don’t have a problem with people pushing back on claims that are too strong for what is presented. That’s just healthy discourse. I have an issue with people whose knee jerk reaction is to complain about a new language or really demand a justification for it’s existence.

                                1. 1

                                  There is nothing wrong with trying to get people to use the language you made. If people like it, if the ideas make sense, they should use it.

                                  No one needs permission to create a new language or to show it to people.

                                  1. 1

                                    Back when I was in university, I had a lot of ideas for that second one. I implemented some of them, and they usually turned out to be less good in practice than in my head (I spent a lot of time on a weird concatenative/actor hybrid). But doing those implementations taught me a lot about language implementation and design.

                                    I don’t do language development at the moment - my job doesn’t call for it, and I haven’t had the motivation to code recreationally for the last year and a half. But the last language project I did was solidly the first kind: I made a weird little Lisp just for my own enjoyment, and all the exploration I did of unusual implementation details were entirely because they seemed like they’d be fun to tinker with, not because I thought they’d ever amount to The Next Big Thing.

                                2. 1

                                  Yes, and part of the process of creating a new language is also the enjoyment! PL is also a very deep field; there are so many subfields to learn and experiment in. Sometimes the best way to do so is to create many small programming languages and throw them away.

                                  Aside: I believe that learning how to develop programming languages can be valuable in industry. We encounter internal DSLs more often than we realize, and they can be decent ways of modeling and solving domain-specific problems in industry.

                                  1. 2

                                    You also learn how metaprogram doing this, which can be quite valuable, IME

                                  2. 1

                                    Made me think of this classic:

                                    I’m doing a (free) operating system (just a hobby, won’t be big and professional like gnu) for 386(486) AT clones.

                                  3. 7

                                    If you want to assign a variable conditionally in Python you have to declare it first, and then mutate it from inside the if statement, and this just didn’t sit right with me.

                                    Fun fact, you don’t actually have to declare the variable before the if statement. How scope works for Python’s if statement is somewhat weird, in that you can introduce a new binding for the outside scope inside the if statement. This would be valid:

                                    if True:
                                         a = 5
                                    print(a)
                                    

                                    And this would raise a NameError:

                                    if False:
                                         a = 5
                                    print(a)
                                    

                                    I’m certainly more interested in Ruby than Python as a language, coming from a Racket (Scheme) background. I’ve encountered and contributed to DSLs professionally, and my hypothesis would be that Ruby provides a more approachable way of working with DSLs.

                                    I consider TypeScript to be the gold standard when it comes to type systems on top of dynamic languages.

                                    TypeScript is interesting. From my understanding, its philosophy is to produce equally-performant JavaScript code. This means that, if the TypeScript compiler is wrong, you don’t have any runtime checks to enforce the types you’ve declared. A small interesting example might be:

                                    function add(arr: (string | number)[]) {
                                      arr.push('a');
                                    }
                                    
                                    let myArr: number[] = [1, 2, 3, 4, 5];
                                    
                                    add(myArr);
                                    
                                    console.log(myArr); // [1, 2, 3, 4, 5, 'a']
                                    

                                    What Typed Racket (gradually-typed DSL for Racket) does is also introduce runtime contract checks between untyped and typed module boundaries. This helps enforce correctness during the runtime.

                                    1. 3

                                      Python’s scoping rules are really bad. Everything is var scoped in JavaScript terms, but it’s not explicit, it’s a side effect of using = in a function body. They added nonlocal in Python 3, but instead of fixing the problem, it just extends it.

                                      >>> x = 0
                                      >>> def f():
                                      ...   nonlocal x
                                      ...   x = 1
                                      ...
                                        File "<stdin>", line 2
                                      SyntaxError: no binding for nonlocal 'x' found
                                      >>> def g():
                                      ...  y = 0
                                      ...  def h():
                                      ...    y = 1
                                      ...  h()
                                      ...
                                      >>> g() # OK
                                      

                                      Why should I care if the x in the outer scope is at function scope or file scope? Just give me the x in the outer scope!

                                      Also depending on how you access an undefined variable, you might hit SyntaxError, NameError, or UnboundLocalError. Good luck catching them all!

                                      1. 2

                                        I’m surprised TypeScript doesn’t detect that type error at compile time. (I confirm that TypeScript has no runtime type checks, so that’s the only time it could detect such an error.) The reason I’m surprised is that the Flow type checker does detect it at compile time:

                                        add(myArr);
                                        

                                        ^ Cannot call add with myArr bound to arr because string [1] is incompatible with number [2] in array element. Arrays are invariantly typed. See https://flow.org/en/docs/faq/#why-cant-i-pass-an-arraystring-to-a-function-that-takes-an-arraystring-number. [incompatible-call]

                                        TypeScript does warn you about similar code where myArr or add’s parameter arr are marked as readonly arrays, but with your example, where you intentionally mutate the passed array, TypeScript doesn’t see the problem.

                                        I wonder why the TypeScript developers didn’t implement this error that Flow has supported for years. Would such an error have lots of false positives? Would it be expensive to check for?

                                        1. 4

                                          TypeScript has no runtime type checks

                                          It has the same runtime type checks as JavaScript.

                                          The reason this program is accepted is discussed in the TypeScript FAQ and it’s one of the design differences from Flow that made it easier to adopt outside Facebook.