12 ms·
Pyret Programming Language
- smitty1e 5y ago+1 for the "lambda bones" logo.
- deleted 5y ago[deleted]
- scns 5y agoHer name is Bonnie. https://en.m.wikipedia.org/wiki/Anne_Bonny https://en.m.wikipedia.org/wiki/Anne_Bonny
- teruakohatu 5y agoI really like the in-function documentation and unit like testing in the where clause. > # this is true > ((1 / 3) * 3) == 1 This worries me. I know it is true mathamatically, but experience tells me trusting floats is a recipe for disaster. A approximate equal operator is safer. Floats are such a leaky abstraction it is in my opinion better students know this early on.
- klyrs 5y agoThe article doesn't really say what's going on under the hood but I'd guess that division of integers makes rationals... > Pyret has numbers, because we believe an 8GB machine should not limit students to using just 32 bits. Emphasis mine. WTF, author. But the Java sample below saying "this is false" implies that floats are a problem that is being avoided. The only reasonable solution is rationals... right?
- adjkant 5y agoYep, this is a project out of the same world as Racket which does a similar thing. If you go into the editor/REPL (https://code.pyret.org/editor https://code.pyret.org/editor) and enter 1/3, you'll see that it gets rendered as 0.3 repeating (with a bar, not some arbitrary rounding) or if you click on it, directly as 1/3.
- recursive 5y ago`1 / 3` doesn't produce a float in pyret.
- agumonkey 5y agoit's a lisp descendant it has, most probably, a full numerical tower
- skrishnamurthi 5y agoPartial, not as full as Scheme.
- na85 5y agoMany languages treat the construction 1/3 As a rational type, and do not convert to float unless you cast. Common Lisp comes immediately to mind. Evidently pyret is another.
- tromp 5y agoHaskell supports rationals with module Data.Ratio, but uses a slightly different syntax: 1 % 3
- skrishnamurthi 5y agoYou should try it and see what it does when you force it to use floats. You may find it interesting in light of your "leaky abstraction" comment. Pyret is designed precisely to make that point clear.
- renox 5y agoFloats are really a poor representation for reals, float-intervals like Frink does are much cleaner but our FPU/SIMD sucks for these kind just think about changing the rounding very often..
- bayesian_horse 5y agoMy criticism is that this language is very similar to Python and might very well confuse students who ultimately have to switch to Python or other languages.
- AlphaSite 5y agoHonestly this looks much closer to ruby than Python, implicit returns etc are very unpythonic, it’s not white space sensitive, etc.
- keithalewis 5y agoIf you only know python...
- aranchelk 5y agoTo me it looks a lot more like Haskell than anything, e.g. :: for type signatures, sum types, pattern matches, etc. And some Ruby with the end keyword to close blocks.
- scns 5y agoStudents switching from this to a "real world language" would be disappointed if it does not have Algebraic Data Types, pretty sure about this. Once you learned about them in SML, OCaml, Haskell or one of their descendants, which include Pyret, Elm, ReasonML/ReScript, Rust and Purescript, you feel lucky if you can use Kotlin and approximate them with sealed classes. We will see, maybe C++, Java and C# add them in the next 5 years.
- gsliepen 5y agoC++17 added std::variant (https://en.cppreference.com/w/cpp/utility/variant https://en.cppreference.com/w/cpp/utility/variant) and other types so algebraic data types are now officially part of the standard. Of course, it's not as compact to write as in Pyret, especially since there's no pattern matching switch statement (yet).
- 5y ago
- dang 5y agoSome past related threads: Pyret – A language exploring scripting and functional programming - https://news.ycombinator.com/item?id=13185759 https://news.ycombinator.com/item?id=13185759 - Dec 2016 (267 comments) A Case for the Pyret Programming Language - https://news.ycombinator.com/item?id=11986977 https://news.ycombinator.com/item?id=11986977 - June 2016 (37 comments) Start Coding in Pyret - https://news.ycombinator.com/item?id=9070834 https://news.ycombinator.com/item?id=9070834 - Feb 2015 (22 comments) Pyret: A new programming language from the creators of Racket - https://news.ycombinator.com/item?id=6701688 https://news.ycombinator.com/item?id=6701688 - Nov 2013 (283 comments)
- cabalamat 5y agoOverall this looks quite nice. I like the way types can be defined but if they are not they can be anything. Are these types checked anywhere? I think they should be checked at compile-time wherever possible, and optionally at run time too (I say optionally as the checks might make it slow, so they could be checked in development but perhaps not in production).
- justinpombrio 5y agoIIRC, they're checked at run-time but not compile-time. And to avoid the speed issue (you're right: it really can get really slow), it only checks the top-level type. E.g. `List<Number>` just checks that it's a list.
- cabalamat 5y ago> they're checked at run-time but not compile-time Do they intend to add this? I think it would make a big difference. It would make thje language more like Haskell, where lots of bugs would be caught at compile time. > it only checks the top-level type. E.g. `List<Number>` just checks that it's a list. That's fair enough because otherwise it might have to go though potentially very big data structures. Maybe there could be a command `strict_check(aDataStructure)` which would only get executed when type checking is on and would recurse into a data structure checking everything.
- scns 5y agoIt is used to to teach children. Spoken the name sounds like pirate. No snark intended.
- cabalamat 5y agoI'm not sure if this was intended as a reply to my comment. In any case, I would suggest that a language be powerful and simple enough that it can do a wide range of tasks including teaching children, GUI apps, web apps, AI research, scripting, etc. Python does this and Pyret should aspire to do it too.
- fnord77 5y agofun to-celsius(f): (f - 32) * (5 / 9) end It looks like abbreviated python.
- cormacrelf 5y agoIt seems pretty bad to have kebab-case identifiers in a language that also has an infix subtraction operator -. The only languages I know that allow kebab-case idents are lisps, where subtraction is (- prefix notation). From the examples: lam(actual): num-abs(actual - target) < delta end This is a new, even worse kind of "whitespace significance" than indentation. Is it a function called `num-abs` or a variable `num` minus `abs(actual - target)`? I can't tell if the language would allow `actual-target` as subtraction.
- deleted 5y ago[deleted]
- nostrademons 5y agoDylan had kebab-case idents and infix operators. It worked okay because you have to separate infix operators with a space anyway; omitting it is a syntax error. In practice I doubt this would trip me up because every coding standard I've worked with has mandated spaces around infix operators. I suppose it might be a lot more confusing if you're used to coding standards that allow you to omit them, but my understanding is that's a minority.
- cormacrelf 5y agoMaybe it would be okay with syntax highlighting and a careerful of code formatting muscle memory, but how would that fare in an educational context? > "Pyret is a programming language designed to serve as an outstanding choice for programming education"
- chowells 5y agoOnly having one correct way to do something with very simple rules (always put whitespace around operators) is easy for students. It's when the rules are complicated with exceptions and multiple correct ways that things get hard to learn.
- skrishnamurthi 5y agoIt's been working great, actually. https://news.ycombinator.com/item?id=28265117 https://news.ycombinator.com/item?id=28265117
- gigatexal 5y agoI like the idea of the where clause to include tests.
- xpe 5y agoI don't care for the name "where" since it makes me think that is is a place to define bindings, like Haskell. I would prefer a term like "expect" or "tests".
- skrishnamurthi 5y agoIt doesn't read fluidly. We care a lot about how our programs are verbalized. We were well aware of the Haskell use, but most of our users have not seen or even heard of Haskell before. So that's not a real problem here. People who don't have Haskell experience find it utterly unsurprising that what follows `where` are the examples/tests. So I think your expectation is being set overly by your Haskell experience.
- bialpio 5y agoI like the idea of attaching tests to the function itself - oftentimes I'm finding myself combing through the unit tests for various components to understand the expectations around how they are meant to be used (especially when they are not documented well enough), I feel this approach could help in this aspect (and also with adding new test cases that could have been missed).
- scns 5y agoElixir (Rust too IIRC) check code in doccomments for correctness.
- mdew 5y agoAnd in python you can use doctests (tests inside de docstrings of functions)
- bialpio 5y agoThat's also pretty nice, although elevating those tests to be first-class-citizens makes more sense to me. My approach is that "code is truth, despite what the comment says", and docstrings feel too much like comments, but I haven't used Python professionally that much so I just may not be used to those.
- piperswe 5y agoI haven't used doctests in Python, but I have in Rust. It really helps that any code blocks in a docstring is a doctest by default, so they ensure that examples in your documentation stay evergreen. It's nice to know that if there's a code example in documentation, it will compile and run properly and hasn't been broken.
- Waterluvian 5y agoPractically speaking how useful are the Rust doctests? I thought they looked like a genius idea but I don’t get how they work 95% of the time when examples don’t come with all the plumbing required to make valid state for a function to actually work on.
- eterevsky 5y ago> # this is true > ((1 / 3) * 3) == 1 This is a slippery slope. Early versions of Dart tried to use rational numbers by default, but then it was cancelled because denominator size can grow exponentially. Also, I seriously doubt you can make a language that will correctly resolve checks like this one: sin(pi / 6) == 1 / 2
- 0-_-0 5y agoThe Wolfram language successfully resolves it: https://www.wolframalpha.com/input/?i=sin%28pi+%2F+6%29+%3D%3D+1+%2F+2+ https://www.wolframalpha.com/input/?i=sin%28pi+%2F+6%29+%3D%...
- mscharrer 5y agoWolfram works with the full mathematical expression tree. It works very well in practice but the equality test is undecidable in general.
- eterevsky 5y agoYes, I should have written "practical programming language". It definitely possible to resolve many equations like this (though not all of them), but is quite a slow process, which is ok for a math system like Mathematica, but not for a real-life programming language.
- lolinder 5y ago"Real-life programming language" or "practical programming language" assumes that there's only one acceptable set of trade-offs for all "real-life" or "practical" problems. I suspect that what you actually meant was "a programming language designed to create industrial-strength consumer or business software". As one of the maintainers has noted repeatedly on this thread, Pyret is a "real-life programming language" whose purpose is educational. Mathematica is a "real-life programming language" whose purpose is solving math equations. Performance isn't much of an issue in either case, so it's a perfectly acceptable trade-off. That these languages weren't designed with your use case in mind doesn't make them illegitimate or inferior languages.
- satyanash 5y agoThe ruby comparison is unfair: o = Object.new def o.my_method(x) self.y + x end def o.y 10 end o.my_method(5) == 15 # true method_as_fun = o.my_method # Wrong number of arguments, 0 for 1 The last line is actually doing: method_as_fun = o.my_method() Which should make the error message obvious. Ruby makes this syntax optional for readability purposes, which becomes obvious once you start going through real world ruby code.
- danwills 5y agoI think if you put more newlines in your code example (at least two per code-line) it might come through the HN formatting thing better?
- lluu 5y agoThe way to do the last bit in Ruby is: method_as_fun = o.method(:my_method) method_as_fun.call(5) # 15
- catwell 5y agoYes, that would be: method = o.method(:my_method) method.call(5) # or method[5], or method.(5) If you really want a "function" that you can call with parens: Kernel.define_method(:method_as_fun, &method) (Definitely don't do that last bit in a real project...)
- jonnytran 5y agoAnd before someone criticizes Ruby for being inconsistent in how the method is called, Ruby isn't a callable oriented language [1]. The common case is calling methods, so the fact that you need to say `.call(5)` both makes it more consistent and makes real code more concise, especially when making DSLs where chaining is really useful. 1: https://yehudakatz.com/2010/02/21/ruby-is-not-a-callable-oriented-language/ https://yehudakatz.com/2010/02/21/ruby-is-not-a-callable-ori...
- trombonechamp 5y agoI love this. I think people often underestimate the value of dynamic runtime checks. For certain applications, e.g. many types of scientific/exploratory software, dynamic checks and static checkcs have nearly identical utility. But static checks can get really tricky to work with as a developer. I built a library for doing modular runtime verification in Python (https://github.com/mwshinn/paranoidscientist https://github.com/mwshinn/paranoidscientist) and evaluated it for scientific software. In the end, it was pretty effective, but not perfect, and there are some major changes I would make if I were to do this again. One problem was that some of the most important cases to check were important because they were difficult to check. (E.g. some function arguments change the meaning other arguments - this is extremely common in major frameworks like numpy/scipy.) By contrast, the flashiest feature in my package was runtime checking of hyperproperties (i.e. checking properties like monotonicity or concavity that depend on relationships between multiple executions of the function), but this was rarely used in practice. The two most common criticisms I hear about runtime checking are (a) it is just an assert statement under the hood, and (b) the performance hit is unacceptable and the only solution is static checks. Regarding (a), sure, they may reduce to assert statements, but most idioms in programming also "reduce to something under the hood". The question is whether dynamically-checked (refinement) types/predicates are a useful abstraction, and in my experience, yes they are. Regarding (b), you probably don't want to use runtime checks on software intended to be run primarily by people other than the developers. But many classes of problems, software is written as a means of discovery rather than as a tool for someone else to accomplish a particular task. For these problems, runtime checks and static checks are approximately equally useful. Static checks are nice to avoid because they can get you into deep water really quickly, so their scope can be quite limited. Also, people tend to overestimate the performance penalty of dynamic checks. Even complex checks often incur no more than a 10% performance penalty.
- odipar 5y agohey, I like your work on Paranoid Scientist. I've never come across hyper-properties: is this something you invented? Regarding hyper-properties: I assume they only work on immutable data values, otherwise it would be hard to manage historical objects so that they can be part of any of the predicates. I'm working on a similar project that you may find interesting: https://odipar.github.io/manikin/ https://odipar.github.io/manikin/. I may want to include hyper-properties in future releases. edit: found this on hyperproperties: https://lamport.azurewebsites.net/pubs/hyper2.pdf https://lamport.azurewebsites.net/pubs/hyper2.pdf
- Maksadbek 5y agoThe syntax is pretty much like Python and ruby: “end” to declare end of block statements and colon to start a block statement. But why to use “fun” to declare a function when “def” could be used. The same in other languages: function, func, fun, fn, etc.
- Okkef 5y agopython doesn't use end. To be honest, as a python programmemr the syntax looks quite alien.
- scns 5y agoMaybe because it should be fun to use? NSI. I prefer fun to fn and func, because it aligns nicely with four spaces a tab formatting.
- skrishnamurthi 5y agoBecause `def` suggests there is only one kind of thing we're defining (functions), when we could be defining any number of things: functions, type aliases, algebraic datatypes, tests, etc. So we use `fun` for functions, and different keywords (e.g., `examples` for examples) for other things. You should really be questioning why `def` was used for functions.
- Mikeb85 5y agoLol the syntax is basically Ocaml with a tad less noise.
- throw_m239339 5y agoNever heard about it before, it looks well done. Very interesting language. First a great point about the homepage: it goes directly to business, no marketing buzzwords, no stupid mascot, one glance at that page and any developer gets a very good idea of what that language does and doesn't. Second yes, they are very interesting choices and functions. However: https://github.com/brownplt/pyret-lang https://github.com/brownplt/pyret-lang It's implemented in Javascript? This is a kind of no started for the kind of app I do, personally. But as a stand alone language which interpreter would be written in C/C++ and could be dropped into an existing native app, it would be interesting.
- skrishnamurthi 5y agoWell, actually, it's implemented in Pyret itself (-:. But it currently compiles down to JavaScript. Our goal is to create an awesome language for certain educational settings, and many of our users (e.g., schools) are on restricted machines that can't install desktop software. The browser is the one platform they can easily access, and it also saves teachers from turning into sysadmins (to install, upgrade, etc.). Hence our browser-based delivery. There is also a CLI. And in principle, someone could write a back-end that targets native code, etc. We don't have the resources to do that right now (but it's all Open Source).
- ilyash 5y agoI have considered different constructs like "where:" to be placed in code blocks (such as function) when working on Next Generation Shell. I have decided against because these constructs will not be executed at runtime (when the function is called) and therefore I assume it will be at least somewhat confusing. For tests, NGS has "TEST" keyword which can be placed at beginning of any line. The test is everything till end of that line. I typically place these below functions that they test.
- chajath 5y agoWhat pain point of Python as an education language is Pyret trying to address? Union type might be vaguely useful, although some of these use cases can be modelled as inheritance or typed enums.
- jpolitz 5y agoThis is a good question! We addressed this explicitly in our (new) book that starts in Pyret and transitions to Python: https://dcic-world.org/2021-08-21/part_appendix.html#%28part._pyret-vs-python%29 https://dcic-world.org/2021-08-21/part_appendix.html#%28part...
- sharno 5y agoIMHO, Union types are the one the most important features that should have been in programming languages since C. And I believe it would have made our software much more bug free than it is generally now. Enums in all languages should be Rust like enums with exhaustive checking and allow recursive definitions.
- dTal 5y agoI was excited that Pyret, which I was previously familiar with as a Racket #lang, had evidently gained enough independence to warrant its own website that does not even mention Racket. What a vindication of the #lang system! Then I read this: "Ultimately, Racket’s #lang facilities, though designed to create new languages—and a great prototyping ground for Pyret—proved to not be quite enough to support a language creation process of the scale of Pyret" I find this rather sad. The PLT group, dogfooding their flagship product's unique selling point, was not able to achieve their goals and switched to Javascript. I hope that one day it may once again be a Racket #lang.
- srfsrvsr 5y agoIs #lang really Racket's USP? I vaguely get that the idea is an extension of the Unix "shebang" convention to files which define modules. It might be preferable to a system based on file extensions or file associations (it's certainly less brittle). I guess the question is whether it's better than directives of the form "import(lang, file)", in other words, explicitly naming the interpretation language for each file that's imported. Naturally one could set a default so that a plain "import(file)" would do the right thing. A project full of files in extremely heterogenous languages would make make #lang more appealing, but it would also be possible to build some kind of file association system within Racket—personally I would prefer to put the #lang info in the filename or the path than stick it ("intrusively") into the file.
- dTal 5y ago#lang is much more than shebangs. Racket #langs are implemented on top of Racket - they can be nothing more than alternative syntaxes, or they can have different semantics (written in Racket). This has the effect of rendering different Racket #langs interoperable within a project. This is wildly powerful - someone reimplemented Python entirely as a #lang, for instance, which meant that Racket could use (pure) Python libraries directly, and vice versa. It's an entirely different philosophy, which aims to allow to use "the best tool for the job" even within a project. Need a DSL? Write one!
- 5y ago
- da39a3ee 5y agoIt seems like a bad idea to use the same “where” syntax for definitions and test cases, especially since a major aim of this is education.
- jpolitz 5y agoThe `where:` syntax ought to only be for test cases attached to functions. Maybe this comment is a useful answer: https://news.ycombinator.com/item?id=28265210 https://news.ycombinator.com/item?id=28265210
- replyifuagree 5y agoAm I the only one who came to this thread looking for good code pirate jokes?
- jpolitz 5y agohttps://blog.brownplt.org/2014/04/01/var-vs-yar.html https://blog.brownplt.org/2014/04/01/var-vs-yar.html
- 8589934591 5y agoA new book which serves as an introduction to CS in Brown university has been released just yesterday. It uses Pyret. https://dcic-world.org/2021-08-21/index.html https://dcic-world.org/2021-08-21/index.html PAPL - https://papl.cs.brown.edu/2020/ https://papl.cs.brown.edu/2020/ is an older version of the current book.
- jpolitz 5y agoThanks for including this! Tweet thread explainer: https://twitter.com/ShriramKMurthi/status/1429181263487844354 https://twitter.com/ShriramKMurthi/status/142918126348784435...
- NeutralForest 5y agoI wish there were an Emacs mode published on MELPA, to work with Pyret
- thesnowdog 5y agohttps://github.com/brownplt/pyret-lang/tree/master/tools/emacs https://github.com/brownplt/pyret-lang/tree/master/tools/ema...
- NeutralForest 5y agoIt's not on MELPA though