[HN Gopher] Wren is a small, fast, class-based concurrent script... ___________________________________________________________________ Wren is a small, fast, class-based concurrent scripting language Author : ahamez Score : 87 points Date : 2022-08-28 20:02 UTC (2 hours ago) (HTM) web link (wren.io) (TXT) w3m dump (wren.io) | ogogmad wrote: | Haven't classes -- as things which house methods and fields | together -- gone out of fashion? I think the same thing has | happened with inheritance. | | The ontological problem of "does the knife cut the cucumber" or | "does the cucumber get cut with the knife" seems serious. The | "is-a" relationship is also problematic, because does a square | inherit both from rhombus and parallelogram? | newobj wrote: | Only the misapplications you give examples of have gone out of | style, I'd say. | ogogmad wrote: | How do you know when it's a misapplication? What do these | constructs actually model? | [deleted] | Cyberdog wrote: | What on Earth makes you think it's gone out of fashion? Pretty | much all of the most widely-used languages have classes or | analogues, if not full OOP. | ogogmad wrote: | I thought that privileging the first argument of a function, | which is all that separates a method from a function, was | understood to be an ugly hack. I thought that this was | acknowledged now, and only legacy languages are stuck with | it. Julia, Rust and Go don't do this. So it's going out of | fashion and becoming legacy. | | IOW, there was never really a difference between | obj f(obj); | | and class obj {obj f();} | | so the whole idea was a mistake. | | Likewise, obj.f() | | should be synonymous with f(obj) | | and the fact that in some languages it's not is evidence of a | poorly thought-out abstraction. See multiple dispatch for the | death blow. | | There's also a discussion elsewhere here about operator | overloading, and how arithmetic operators don't behave like | methods. | Jtsummers wrote: | > I thought that privileging the first argument of a | function, which is all that separates a method from a | function, was understood to be an ugly hack. I thought that | this was acknowledged now, and only legacy languages are | stuck with it. _Julia, Rust and Go don 't do this_. So it's | going out of fashion and becoming legacy. [emphasis added] | | What? | | Go has methods which "privilege" the first argument to | functions: | | https://go.dev/tour/methods/1 func (v | Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + | v.Y*v.Y) } | | Though it moves the argument out of the argument list and | between the _func_ keyword and method name. | | Rust also has a notion of methods: | | https://doc.rust-lang.org/rust-by-example/fn/methods.html | | Were you thinking of other languages? | lifthrasiir wrote: | You can have multiple `f` with different "arguments" (if | you consider a receiver a part of arguments) without the | full multimethod, which is actually pretty hard to get it | right and only one language out of your examples (Julia) | does that. Other two languages (Rust and Go) fully retain | classes, slightly obscured to fit with traits and | interfaces respectively. | jakelazaroff wrote: | obj.f() shouldn't necessarily be synonymous with f(obj) | though. How would the latter case handle private fields, | for example? | ok_dad wrote: | > The ontological problem of "does the knife cut the cucumber" | or "does the cucumber get cut with the knife" seems serious. | | Kinda both! The knife (aka: the "Cutter") can perform a "Cut" | action on any object (aka: the "Cutable"), but the Cutable | objects have to receive the Cut action and determine if the | Cutter has enough "Cutter.Strength" to Cut the Cutable. | | I think the failure of OOP is applying it to things that aren't | appropriate or creating a Factory pattern that causes over- | abstraction. OOP in itself isn't bad, much like PHP or Windows | has their place even though they get shit on all the time, but | the lack of care applying OOP (or any other pattern or | architecture) is the bad part. | mananaysiempre wrote: | You seem to have conflated several different things. | | - Single dispatch--having a single distinguished "receiver" for | each operation determine how to perform it. Can get very | awkward when the problem domain does not work that way | (algebraic operations of all kinds), but it's still nearly | universal outside languages with CLOS heritage (Clojure, | Julia). | | - Having classes be distinct from (though possibly a subset of) | objects. Less elegant, but also nearly universal except for | rare holdouts (JavaScript). Nystrom's book explains his opinion | on this. Incidentally, it took people until 2005 (!) to figure | out[1] how to make multiple dispatch work in a prototype-based | (that is, classless) setting. | | - Objects, that is self-contained bundles of state and | behaviour. (Arguably a subset of single dispatch.) Wonderful | when it fits, painful when it doesn't (syntax trees and other | places when you want to match pieces of structure). Nystrom's | explanation of how the Visitor pattern addresses this is very | good, and pattern matching in Scala and (recently) Python works | roughly along these lines in a setting of (mostly) pure | objects. | | Unfortunately, when you want both the set of verbs and the set | of nouns to be extensible (the "expression problem"), something | more powerful is needed, as both pure objects and pure | functions struggle here. "Protocols" in Clojure and Swift are | among the ways people are trying to address this, but I can't | say there is a singular accepted solution yet. | | - Subtyping, having some groups of thingies be included in | other groups of thingies ("is-a", or rather "every-*-is-a-*"). | Widely accepted to be necessary in one way or another. Rarely | fits into a tree of inclusions--"diamonds" are fairly common. | | One issue that was understood relatively late is "variance": | instead of an operation that takes Xs and gives Ys, you can | substitute an operation that takes Xs _or something more | general_ ("negative position", "contravariant") and gives Ys | _or something more specific_ ("positive position", | "covariant"). In particular, you can _get_ the side of a | rhombus or something more specific (thus e.g. getting the side | of a square), but _set_ the side of a rhombus or something more | general (thus e.g. simultaneously setting all sides of a | quadrilateral at once). Therefore _if_ your operations are | packaged together with data into objects, and _if_ those | objects are mutable, squares cannot be a subtype (nor a | supertype) of rhombuses. | | - Implementation inheritance. Has indeed gone out of fashion, | comparatively speaking, especially the painful diamond kind | (unlike same for subtyping, which is as necessary as ever). | Remains a convenient shortcut in most languages that do | objects, outside of a few obscure systems that provide more | powerful replacements (parents in Self, delegation in Snit, | aggregation in pre-WinRT COM). | | [1] https://dl.acm.org/doi/10.1007/11531142_14 | dataangel wrote: | Is it statically typed? | IshKebab wrote: | I have yet to find any nice easy "normal" (like Typescript or | Dart) statically typed languages that can be easily embedded. | In the Rust space there's Gluon which is statically typed but | has a really weird syntax and is functional, and there's Rhai | which is really quite nice but dynamically typed. | | I guess static type checking is probably more work on its own | than writing an entire dynamically typed language. | 10000truths wrote: | Have you checked out AngelScript? | | https://www.angelcode.com/angelscript/ | goodpaul6 wrote: | I'm currently working on Tiny [0], a small statically typed | programming languages which is even more minimal than Wren. | | [0] https://github.com/goodpaul6/Tiny | fm77 wrote: | Very interesting! | | BTW: I think I found a typo: "MATCH2("+=", PERCENTEQUAL);" | -- should be "%=" ?? | Cyberdog wrote: | No: | https://wren.io/try/?code=G4QwTgBAZg9jEF4ICIBG5kChbyQFgCZMBl... | chaosprint wrote: | Cool. Can this be embedded in Rust? Does it support wasm32 | (probably this is how the web demo runs?)? | hwers wrote: | Whats wasm32 (vs just normal wasm)? | stefanos82 wrote: | Seems like it https://github.com/pwoolcoc/wren-rs | 5d8767c68926 wrote: | Note that the last commit was 8 years ago (when Rust hit | 1.0). | stefanos82 wrote: | Well, basically I copied the second link from | https://github.com/wren-lang/wren/wiki/Language-Bindings | just randomly; I didn't think to check the release date to | be honest with you, my bad. | | The other Rust projects seems more updated, like | https://github.com/Jengamon/ruwren was last updated in May | 9. | xscott wrote: | Wren seems pretty elegant, but it makes the same mistake a lot of | languages do when it comes to operator overloading. If you put | the binary operator as a method on the first object, then there | isn't a simple way to have "builtin_object <operator> | your_object". | | For instance, Wren doesn't provide complex numbers, so you aren't | going to get a nice syntax for "1/z" or similar. I could make | similar examples with scalar multiplication for vectors, | matrices, or Numpy-style arrays, etc... | | Python and other languages have fallbacks to work around this, | but Wren does not. And really, I think of binary operators as 2 | argument functions, not methods on the left object. | TazeTSchnitzel wrote: | This is an area where typeclasses (as they're known in Haskell) | or traits (as they're known in Rust) really shine. | fiddlerwoaroof wrote: | Or multimethods (as found in CL/Clojure/Dylan/Julia) | samatman wrote: | I'm surprised to hear that, given how closely Wren's semantics | resemble that of Lua's. | | Lua uses the left metatable's metamethod for two tables or | userdata, or the metamethod if the binary operator has a | primitive on one side of the argument. | | This gives elegant results at the expense of some | implementation complexity: there's no mechanism to figure out | what's happening inside the metamethod, all you know is that if | both sides are metatable-able, you're in the left side's | method. | fiddlerwoaroof wrote: | Can't you solve this particular issue with extension methods | the way Kotlin and C# do? | mncharity wrote: | I _really_ look forward to a language with first-class explicit | algebras, with operators, laws, equality, types. Rather than ad | hocery on multimethods, or kludgery slathered thick over single | dispatch, or the ever popular "you just can't get there from | here". | | "1 is not an object; + is not a message"... I'm failing to find | the quote, but it dates back like 40 years to smalltalk, and | yet here we still are. | dagmx wrote: | As a complete aside, Wren was also the name of the in-house | renderer at Rhythm and Hues. Used in award winning films like | Life of Pi before they went bankrupt. | | Anyway not really related, but it's the first thing that popped | into my mind since it was my first gig. | Kyrio wrote: | Originally made by Bob Nystrom [1] who now works on Dart, it is | now maintained by ruby0x1 who is a game developer and most | importantly creator of a game engine that uses Wren as a | scripting language [2]. Unfortunately Luxe is still not publicly | available (closed beta), which I admit is a bit of a frustration | for me as I've been following development for a few years, but it | does show a lot of promise and in the meantime I've become a | happy user of Godot. I keep Wren in the back of my mind as an | easy-to-embed scripting language in cases where you could | integrate Lua (which Wren outspeeds) but not LuaJIT. | | [1] https://news.ycombinator.com/user?id=munificent | | [2] https://luxeengine.com/ | tamsaraas wrote: | I think this is one of the best languages that i ever seen | before. All interested by me concepts are covered, that open | ability to write different complex logic for manipulating data. | | WoW. Thank you very much for all of that! This is really great, | and has powerful potential to become inner-script language for | many different projects where must be ability to write some kind | of macroses, scripts inside the main enveriopment (game engines, | game emulators) | | Good job! I feel that you have wide experience in scripting | languages that developed inside some big project for inner | purposes inside a big app. | pmontra wrote: | I like about everything except the leading underscores for | _fields and for __static_fields. They look really bad, a remnant | of the 80s. I understand that one of the goals is keeping the VM | small but there must be another way. | dataangel wrote: | Python does it and is still very much alive. It's also | idiomatic in C++. | Cyberdog wrote: | And PHP still has __construct() and friends. It still looks | like a remnant of the '80s, though. | b3morales wrote: | It's a neat little language. It was created by the author of | [Crafting Interpreters][0]; the language in the book (Lox) is | essentially a slimmed-down Wren for teaching. | | [0]:https://craftinginterpreters.com ___________________________________________________________________ (page generated 2022-08-28 23:00 UTC)