The Verse Programming Language [pdf]
simon.peytonjones.org
simon.peytonjones.org
- There are no booleans in the language! Conditionals can still succeed or fail, but failure is defined as returning zero values and success is defined as returning one or more values.
- Verse uses a so-called 'lenient' evaluation strategy which is neither strict nor lazy, but somewhere in-between ("Everything is eventually evaluated, but only when it is ready")
- an expression does not evaluate to a value (like in Haskell), but instead to a sequence of zero or more values
- tries to bring functional logic programming into the mainstream
- Verse uses an effect system for I/O instead of monads
- A type in Verse is "simply a function". E.g. int is the identity function on integers, and fails otherwise
This all looks very mind-bending to me (in a good way). Perhaps Verse will one day be as influential for PL design as Haskell has been.
This is similar to how Icon works: https://en.m.wikipedia.org/wiki/Icon_(programming_language)
https://tratt.net/laurie/research/pubs/html/tratt__experienc...
You can try this type of programming at home, say in JavaScript Make any result or argument be an Array. The problem with nulls goes away because "not there" is represented simply by an empty Array (a.k.a "sequence").
And you will not get null-errors because you can write:
newValue = someValue.filter(...) . map(...) ;
You don't need to test whether filter() returns an empty array or not, the map() will work for empty arrays too but simply do nothing.This is in a sense "generalized programming" because you don't deal with individual values but always with collections of them. I sometimes wonder why I don't use this pattern more often.
And I similarly wondered why I don’t use this sort of pattern more often, but that wondering is what led me to add this caution. It’s a really compelling idea, but probably extremely hard to debug when it goes wrong in a language and idiomatic ecosystem designed for it to go wrong at any time.
But returning an array also makes your functions more general. Maybe in the future you want to modify it so that it does return arrays of length > 1. Evolving the program to that state is then easy if you didn't lock yourself into assumption that this function will never ever need to return more than a single value.
Or, you actually have to use nested arrays to describe that the result might be an error or an array. But now you have to deal with an array which might contain... zero errors or even multiple ones.
That's really not a great way of doing things. Instead, do it the other way around and make null treatable in the same way as arrays are. And if you do that, you end up with what languages like Haskell do.
Empty array in this pattern does not represent an error. It represents the fact that no values you asked for can be found. It is like querying a database. It is not an error if your query finds no values.
The calling code that receives the empty array might decide it is an error or that it is not. And of course you can always throw an error, that can be done with the "throw" keyword.
Getting rid of using nulls by using arrays instead is not about handling errors, but about preventing errors, by changing the semantics of your functions slightly so they never need to return null.
You can say a result was found and that result is an array, possibly an empty array. Or that no result was found which is indicated by returning TOP-LEVEL empty array.
> Or, you actually have to use nested arrays to describe that the result might be an error or an array. But now you have to deal with an array which might contain... zero errors or even multiple ones.
In other words: now you have Array<Array<?>>
And now it is only convention that the outer array must only have 0 or 1 elements. But there is no guarantee and the compiler won't help you since it cannot know. That's why this is the inferior approach compared to turning it around and making it so that null can be mapped and flattened.
Because while handy, it's not universally applicable (just like everything else :-))
I (C programmer, mostly) use sequences more often than you'd expect for parameters[1], but that does not mean that it makes sense to always return sequences.
In a lot of cases, sure, a function should return a sequence of values. In many other cases, it makes no sense - `if (canProceed(x,y,z))` reads more sensibly than `if (canProceed(x, y, z)[0]`.
[1] My string functions mostly lend themselves well to unlimited number of parameters. For example concatenation takes unlimited parameters and concats all of them, which it returns. Same with substring searching - take a source string and an unlimited number of substrings to find.
Whatever you can do with a single value you can also do with an array containing just that single value. How practical that is depends on the language used. In JS after ES6 arrays are syntactically quite nice and easy to use.
This includes a state monad that allows you to apply .map just like an array and a maybe monad that let's you do the same on values that might be nullish.
Sounds like we are still clinging on to laziness in some regard, I wish we could get shod of it entirely. Although laziness makes doing Leetcode problems in Haskell really fun, Idris got it right when they opted for strict evaluation for predictable memory performance.
I'm not convinced. Making non-determinism a first-class feature in the language might be good if you simply care about logical specifications that might enable you to prove something correct, but a real-world program implementation has to make heuristic choices for efficiency as to when to evaluate what (and perhaps where, especially in a parallel/distributed setting), and just stating that evaluation is "lenient" isn't really saying anything worthwhile. So this kind of design choice will ultimately be expressed with ugly hacks, as with e.g. Prolog where the 'cut' feature is used to override the default search strategy.
I'm decidedly in the not convinced camp.
Does the language address common pain points like modifying data structures? Does it make it easy to extend existing code even without having the ability to change it?
jq is very much like this too, as it has pervasive generators and backtracking, but unlike Icon jq does not distinguish between "returning" a value vs. "suspending" (yielding) a value.
The jq way kinda means you have to have booleans, and so jq does.
I'm suspicious of the no-booleans approach. After all, one could also have no integers (the Lambda Calculus doesn't have integers, having only function values!). Boolean values are just useful to have, and being able to obtain boolean values from predicates is useful too. One could do the Icon/Verse thing of failure is false / anything is true, but provide an adapter function that produces actual boolean values for when you need them.
Has Haskell really been that influential though? It seems to me that MLs, Lisps, Schemes, and even Erlang have been more influential.
(To be clear, I am mot necessarily down on Haskell or what part it has played. It’s just that many languages seem to be stealing ideas from the languages I’ve listed more than Haskell, which was the criteria I had in mind.)
> This paper presents type classes, a new approach to ad-hoc polymorphism. Type classes permit overloading of arithmetic operators such as multiplication, and generalise the "eqtype variables" of Standard ML. Type classes extend the Hindley/Milner polymorphic type system ...
And it was my understanding that traits came more from the object-oriented world, such as Self and Smalltalk. Scala and Racket also had them before Rust, and Scala also has type classes.
My understanding is that "trait" is an unfortunately overloaded term. Traits in Rust are much more closely related to Haskell's type classes than to traits in the OOP sense.
Yes, I know that. That's the point.
> SML does not have type classes; your quote points out a deficiency in SML that motivates type classes.
Again, that's the point. It's what "have an influence" means in that it was SML that influenced or inspired Haskell's type classes. And it's part of my overall point of SML being rather influential, although quietly.
> Traits in Rust are much more closely related to Haskell's type classes than to traits in the OOP sense.
I'm not so sure about that from what I have read. But I don't have enough information other than to just point to things I have read.
https://stackoverflow.com/questions/28123453/what-is-the-dif...
While I can't find any concrete information, I would be quite surprised if Rust's traits were influenced by type classes rather than the more OOP interpretation of traits (in the design space of traits vs mixins vs interfaces).
I'm not familiar with the origin of traits/mixins in the OOP world, but my understanding is that they generally contain implementations of methods; they are a "part of" a class. Type classes and Rust traits, however, are more like interfaces. I'm pretty confident you won't find any notion of trait that predates type classes and can define what a Functor or Monad is. My reading of the SO answer you link is that Rust traits started off similar to type classes and have grown closer and closer over time. I'm not sure what a clearer indication of Haskell's influence would look like!
https://en.m.wikipedia.org/wiki/Common_Lisp_Object_System
> Another unusual feature is that methods do not "belong" to classes; classes do not provide a namespace for generic functions or methods. Methods are defined separately from classes, and they have no special access (e.g. "this", "self", or "protected") to class slots.
Of course, the whole idea of having methods as separate entities might sound a bit "alien" today. Still, the idea of traits as abstract contracts, with separate and potentially multiple distinct implementations, comes directly from this, IMHO.
It showed that monads can be used to isolate I/O but have a very real cost when it comes to complexity, that laziness by default is a bad idea and that typeclasses are a good way to introduce ad hoc polymorphism.
Definitely a good result for a research language but far less ground-breaking than ML was (admittedly putting the bar very high).
* I'm a little disheartened to see "Objectively: no. All languages are Turing-complete" in the context of the question of needing another language. It's a throw away comment and largely irrelevant when considering the actual use of programming languages. If one has to state this platitude, it is more accurate to say "theoretically" rather than "objectively", as I think the latter is actually debatable.
* The utility of the choice syntax over comprehension syntax is not clear at all. The choice thing seems neat, but I don't understand why comprehension semantics weren't just extended. Every example of choice seems to refer to sequences and comprehensions anyway to make the meaning clear. Will have to see more examples. Right now, the syntax seems a bit quirky, especially with `false?` thrown in.
* Why is `fst` not named `first`?! The shortening is maddening to me. It saves two characters (negligible savings), decreases readability, and first is probably just as fast to type.
* I'm still not sure why they're creating this language, what problems it solves, and what any of it has to do with a metaverse.
These are professors and language experts, so I'm a bit surprised by the presentation. Also, the idea that this language will be learnable as a first language is ambitious, if not naive.
When you are building simple structures to iterate upon, it makes sense to use the more readable comprehension syntax, where you define a list or set of items and their desired properties.
Yet this terse syntax makes more sense for logic programming, where a lot of the domain logic is built upon generate-and-test patterns; you define a combinatoric search space which is the enumeration of all base value in pairs (or tuples), and check which ones are kept for the next processing steps. When using this pattern, it's clearer to be able to express the space with the shortest syntax rather than the verbose one.
As for the adequacy and need for the language, I have my own ideas on what's needed for the stated use case, and I do agree with the authors that this kind of language will really be easier to learn for people without a programming background; it looks much more like mathematics than the traditional von-Neumann-architecture, continuation-based languages, and its declarative nature may make it easier to approach without having a full understanding of runtime behavior.
I didn’t think otherwise. Many functional languages have comprehension syntax, and I prefer declarative programming.
> When using this pattern, it's clearer to be able to express the space with the shortest syntax rather than the verbose one.
How is
x <- [1,2,3]
or x <- {1,2,3}
more verbose than x := (1|2|3)
? Also, the first and especially second are basically identical to mathematical syntax, but the first implies order better.[(x, y) for x in [1, 3, 5] for y in [2, 7, 8] if x < y]
It's a single monolithic expression that builds the list. The choice syntax however represents each generator and each test as separate expressions, which may even be part of different functions. This seems to offer more flexibility. For example (I don't know the exact syntax):
x:=(1|2); y:=(7|8); x<y; result = (x,y)
Here result is bound to the same values as in the comprehensive list; but these values are yield one at a time, instead of being part of a structure that you traverse.
No writer does this. Why are programmers obsessed with word length to such a degree?
Mathematics uses symbols because there is usually no specific context for an abstract concept, and on other cases it relies on convention to provide context. Shorter names are additionally a side due to the density of information and the ability to write complex symbols on a chalkboard and in LaTeX. The symbols are the meaning and not some shortened version of it.
I am not surprised by this at all. If they really want to create something practical, I would rather employ the creator of Turbo Pascal, than one of the creators of Haskell. To me it seems as SPJ et al. are taking the money to do something fun and interesting, and scratching an itch they had for some time. Nothing wrong with that, but don't expect something that will be useful anytime soon.
SPJ has been implementing features that the industry and real world users wanted in Haskell for decades and yet you expect his cooperation with another great dev and business person like Sweeney to be fooling around and not produce "anything useful anytime soon"?
I recommend you reading the transcript of one of the latest SPJ's podcasts, he speaks both about the role of languages in the real world and about Sweeney's project:
SPJ is an exceptional public speaker, but that involves a lot of talking, a lot of context, audience participation, and a lot of wild gesticulating at slides.
I'm not sure if this talk was recorded, but I am sure if it was the recording will be much better than the slides, the slides are not really designed for consumption outside of the talk context, but rather as a reminder rather than taking notes. At least that's my experience having seen a number of his talks over the years.
Personally I've got used to them like in no time
x = fst(some complex expression)
y = snd(some complex expression) (x, y) = some complex expression
And I’m not for sure if this alignment overrides the readability aspect. Verify few languages have alignment in mind, and even less formatters do, so it isn’t clear why alignment is so strongly needed in this very particular case. And what about third and fourth?That you fall somewhere differently on any or all of those spectrums than the author is fine.
As a sidenote, I found funny his predictions for 2009, because they're not far off from what we currently are aiming for: - 20+ cores - 80+ hardware threads - GPU's with general computing capabilities
Also they both seem to have a preference for using Comic Sans on slides ...
At first I though the "choice" construct would be a way to distribute code execution among multiple computers (using the fact that in a grandiose metaverse, everything would be a connected computer with lots of compute time to spare ?) but there is not much detail.
Also it's not obvious from the slide if there is already a compiler / exécution env at the moment, or how far they are from it.
Now, the names behind this aren't exactly bozos, so I suppose we'll get to know soon.
Wait and see, I guess ?
I honestly cannot wrap my head around how a programming language of all things should solve the "millions of programmers working on a thing"-issue.
It is expected to release in January as part of Fortnight Creative (delayed from this month).
Suppose you wander into a new environment, it contains some object x, and it has some capability f(x). Suppose your avatar or whatever has some code that already integrates with this f(x). You could just call f(x) in advance, and once you enter that environment, it lazily executes f(x). Or maybe I'm way off base here.
Can epic do that ?
Facebook a least "invented" a form a "passing time" (I'm being generous not to call it wasting time) that doubled as an advertising and marketing platform. And even that only took aff with the advent of smartphones, which enabled "using Facebook / twitter on the go" (and, more accurately, "on the loo").
When there's a VR helmet attached in every toilet, though... I'll sell hemoroid creams :)
They're pushing transactions straight from the beginning, which I think is the sanest way for multiple actors to all try to interact with the same world.
And for the compiler to stay sane in dealing with transactions, it's necessary to mark effects, which is also in the slides.
The inclusion of effects & transactions already puts it way outside of the mainstream, even without the Logic stuff (which I admittedly don't understand yet)
Maybe the backtracking concepts are "too built in?" - e.g., (1|2) is not a first-class/reified "amb" object, right? - so if I want to introduce a different search than depth-first backtracking (breadth, dependency-directed), etc., I couldn't directly.
Seems like there could be some confusion between multiple, backtracked values and actual sequences -- this often leads to sub-optimal/confusing Prolog code as well, deciding when you have an explicit control structure vs. backtrack, when to "harden" results using setOf/bagOf/findAll, etc.
For context, Prolog had a culture of "the built-in search is less than wonderful... but good for crafting a problem-appropriate search". II(fuzzily)RC, Mozart/Oz decoupled nondeterministic code (explicit amb, spelled "dis") specification from search, and allowed managing search over nested spaces of unification constraints and threads. With (very fuzzy) less use of backtrack-driven implicit sequences than in Prolog? I so don't remember Icon.
Curiously, https://www2.cs.arizona.edu/icon/books.htm includes a "newish" (2010) book, "Icon Programming for Humanists".
I prefer the jq approach to the Icon approach, which I think means I am suspicious of this aspect of Verse :)
Also, boolean values are inherently useful, and while checking that an expression is empty or not is a boolean predicate, it should be a predicate that produces a boolean value. Otherwise if we have no boolean values then we shouldn't have integer values either and just go back to the Lambda Calculus!
If your language lets you declare your own algebraic data types, there's no need to lean on a built-in Boolean type. You can create types that actually carry all the information you need so that pattern matching provides provenance and data only in the branches that need them.
Robert Harper discusses the idea in some detail here: https://existentialtype.wordpress.com/2011/03/15/boolean-bli...
Would you say the same about Ints or Strings?
The domain of int/str is infinite so there's less sense in redefining a number system for every property you want to model
For small finite domains it makes sense to define your own in terms of the problem domain
In this sense all two-valued types are bools
They are two completely different data types that happen to have identical approximate representations but should be distinguished very strictly in a sufficiently expressive model.
For instance, it should be possible to turn an IBAN into a device screen message but not the opposite, but you can't do it if they are all "strings"; and the two types have different value constraints while a generic VARCHAR has none.
About bools: that's my problem with this. If-statements now operate on anything, instead of just bools. And I don't think that makes sense, unless cheese.
About strings: It's great you can statically differentiate between their types. But if strings don't exist, it makes it a little hard to write WHERE clauses.
Wait, are you hung up on implementation nonsense? Sure, there's a low-level operation that returns a 0 or 1 that you convert into your actually-meaningful data type. But that doesn't need to have a surface language boolean type that's privileged by the language design. And that's what's important here - language design. People write programs in a language, not compiled code. The model the language provides is of critical importance. It's how the users of the language think and how they communicate with each other.
And this isn't abstraction. Boolean is the abstraction. It throws away all but a single bit of information. This is creating data types with semantics that carry far more than that single bit. It's making your code less abstract.
You could make a battle royal game well where people start taking damage when they are 100 units away from the center of the map.
>Why not have a data type that actually expresses that meaning?
It would add unneccessary complexity.
>Wait, are you hung up on implementation nonsense?
The base of what it being abstracted over is not nonsense.
>But that doesn't need to have a surface language boolean type that's privileged by the language design.
If exposing booleans lets people write simpler code then it makes sense to expose it instead of forcing complexity onto everything.
>Boolean is the abstraction.
No, booleans are a concept that the processor understands. Zero is false and nonzero is true. The processor has instructions like like logical and that can operate on these booleans. Branches can happen based off a bit in the status register. A bit has two states which maps to true and false. Booleans are a fundamental concept that is being built upon. The processor has a limited number of data types that it understands. Creating new data types is creating abstractions because those data types do not actually exist. You are simply hiding an actual data type in the new one you are creating.
So... You have some meaning there, don't you? Something beyond the values true or false? Does true mean "is safe" or "is taking damage"? Wouldn't something that actually says what you mean be a lot clearer? More direct? Fewer ideas between the expression and the meaning? Less abstract?
> If exposing booleans lets people write simpler code then it makes sense to expose it instead of forcing complexity onto everything.
Why do you think it's more complex to eliminate a semantic step?
Your last paragraph is... very weird. Do you think languages are required to privilege Boolean over any other 2-type, such that only Booleans are allowed to map to those values in machine code? Not every language is as poorly designed as C. You're not wrapping Booleans, you're creating new types which the compiler gives the exact same representation as Booleans get.
And for what it's worth, processors don't understand zero and one. They're mechanistic circuits that operate on combinations of high and low voltages. Zero and one are interpretations added on top of what's going on. If it's easier to think of high voltage as one and low voltage as zero, maybe it's even easier to think of them as "safe" and "taking damage".
You could name a function that returns a boolean isInSafeZone. From the name it would be clear that true means safe and false means that it isn't.
>Wouldn't something that actually says what you mean be a lot clearer
No, compare "if (player.isInSafeZone())" to "if (player.getSafeZoneState() == SafeZoneState.SAFE)". Endure is extra verbosity that isn't giving you value.
>Fewer ideas between the expression and the meaning?
I don't know what you mean by this. You are creating extra types for every possible condition is introducing more ideas. Why have 1000 boolean types when you can have 1 that interopts with itself.
>Why do you think it's more complex to eliminate a semantic step?
There is more steps in creating a new type, maintaining it, and having to convert it into what you want when you could just use booleans from the start.
>Do you think languages are required to privilege Boolean over any other 2-type
No, even C has typedef. I never implied there was wrapping going on. I meant that you are introducing layers of indirection. It's a case of everything in programming can be solved by creating an interaction except having too many indirections. Indirection is not always the answer even if there is no performance impact.
>processors don't understand zero and one
By the interface that is exposed to programmers they do. Read the manual. For the purposes of making a programming language there is no benefit in going down to the level of voltages. It is an implementation detail that is the processor creator's job to worry about.
But I think mixing this with unification vars is sort of an open research problem?
Plus Haskell had a `data-parallel` mode which used a similar compilation strategy. It was dropped for being very complex and having virtually no users. Plus using too much broadcasting and compiling higher order functions into vectorized code had a serious performance tax.
--
Verse is a functional logic language (like Curry or Mercury).
Verse is a declarative language: a variable names a single value, not a cell whose value changes over time.
Verse is lenient but not strict:
Like strict:, everything gets evaluated in the end
Like lazy: functions can be called before the argument has a value
Verse has an unusual static type system: types are firstclass values.
Verse has an effect system, rather than using monads.
--
Verse is extremely ambitious
Kick functional logic programming out the lab and into the mainstream
Stretches from end users to professional developers
Transactional memory at scale
Very strong stability guarantees
A radical new approach to types [me: predicate functions]
Verse is open
Open spec, open-source compiler, published papers (I hope!)
Before long: a conversation to which you can contribute
That sounds interesting to me. Part of why I don’t like GADTs in OCaml is that it feels like you’re trying to fit a programming language within the syntax of the type system.
> Like lazy: functions can be called before the argument has a value
FYI, jq is just like that. In jq in `def f(g): ...;` `g` is a function value that will be applied to some input of `f`'s choice, and `g` is not evaluated unless `f` invokes it. The actual argument to `f` will be an expression which is wrapped in a closure named `g` while `f` is executing.
Lazy evaluation really is just hidden closures.
Lazy evaluation raises questions like:
How obvious shall the syntax make it that
you will be passing a closure instead of a
value?
Closures of dynamic or indefinite extent?
Can you choose which? How intrusive in the
syntax is that choice?
Does the use of lazy vs. strict infect
callees?
I.e., if I define a function `f` of one
argument of type `T`, must it be able to
take an argument that is a closure that
produces values of type `T`, or must that
be declared separately?
If the latter, does that mean I end up with
two `f`s, one which takes a value of type
`T` and one which takes a closure that
produces (a) value(s) of type `T`?
If so, does that happen automatically or
must I request it?
If the latter, what is the default, and
what happens if some library I want to use
one option doesn't provide it?
Finding a happy medium with some flavor of lazy evaluation but also which doesn't make it hard to understand the performance considerations of it is just very hard. x:=(1|2); y:=(7|8); (x,y)
This stuff just doesn't seem intuitive to me. It's not verbose enough to be obvious to someone who doesn't know what's going on.Looks interesting though; that's a really bright group of people. Be curious to see where their project ends up.
If you just removed like 90% of C++'s useless standard library, and restricted the syntax to purely what's in Strousup's "Tour of C++" book, then I'm pretty sure that would be a pretty acceptable "learn it as a first language" language. Of course in that imaginary world C++ would also not have been deprecated by Rust.
The Python library is even larger and doesn't seem to be a barrier. If you know `std::vector`, `<<`, and `std::sort` it seems you're set to contribute to most code bases.
> C++ would also not have been deprecated by Rust.
That's an overstatement, to say the least.
https://en.cppreference.com/w/cpp/algorithm/transform_reduce
I agree that the C++ example is (one reason) why modern C++ has jumped the shark.
There is a "range" version in C++20 that in use looks more like in other languages. (It is technically C++23, but appears in libraries shipped with C++20.)
That in 2017 the C++ standard committee was still introducing misdesigned cruft like std::reduce to the language says everything you need to be about C++, it's a clusterfuck.
C++ complexity is also its strength. Highly backward compatible, even with C, and multiparadigm. It has classes, but you don't have to use them, it has exceptions, but you don't have to use them, it has templates, lambdas, smart pointers,... and again, you don't have to use them, but they are here if you need them. Even the "deprecated" features of C++ (like most things related to raw pointers) are heavily used today, even in new projects, because they are useful.
Strip 90% of "deprecated" C++ and what you get is essentially Rust, but worse because it still has its C baggage without the advantage of being mostly compatible with C.
(Rust has not replaced C++ in the real world. Not even close.)
You can do many many things in Python without needing to know much other than working with dictionaries.
In C++, doing a sort or a string search is an ordeal. So much of common programming requires so much cognitive overload.
C++ is not an easy language. Not by a long shot.
Python’s standard library is not without its faults but I’m always so frustrated that the C++ STL stops just short of providing many things, and when it does, it requires writing out so much verbiage.
The more your C++ code resembles C, the worse it is.
Lambdas are generic now, and variadics work most places.
Velocity has shot up. Fun, too.
I think this is very subjective. Our minds have been "poisoned" - or rather trained over years - into a very specific way of thinking about expressions like in the example.
A first programming language, however, assumes that the learner hasn't been preconditioned in any way into a certain paradigm. So just keeping the two rules in mind that 1) evaluation is strictly from left to right and 2) an expression evaluates to a sequence of zero or more values immediately makes sense of the example.
Unfortunately it's incredibly hard to "reset" your mind into a state that doesn't know about variable assignments and thinking of variables as singular slots as is the case in Haskell and most other programming languages.
That's why "intuition" is a very subjective thing - your intuition changes with knowledge and experience and both are hard to suppress.
x:=(1|2); y:=(7|8); (x,y)
Doesn't look like any math I'm familiar with.For x in [1,2]: For y in [7,8]: yield (x, y)
[(x, y) for x in [1, 2] for y in [7, 8]] // Python (list comprehension)
{(x, y) | x \in {1, 2}, y \in {7, 8}} // math (set-builder notation)I remember struggling to understand the x = 7 syntax for storing a value in x. My young self was like “so if x is equal to 7, how come we can write x is equal to 8 later? That doesn’t make sense”
If it were
suit := (clubs | diamonds| hearts | spades);
value:= (2..10 | J | Q | K | A);
deck := card(suit, value)
You would recognize it instantly. x 1 2
y |--------------
7 | (1,7) (2,7)
8 | (1,8) (2,8)https://stackoverflow.com/questions/29451291/cartesian-produ...
signalStrength cycle x = cycle \* x
cycleGaps = [19, 40, 40, 40, 40, 40]
cycleStrengths = foldr a (const []) cycleGaps . (\x -> (1, x))
where
a n r (i, xs) = signalStrength m y : r (m, ys)
where
m = i + n
ys@(y : _) = drop n xs
From: https://www.reddit.com/r/haskell/comments/zhjg8m/advent_of_c...Personally I love this headscratching stuff, but I would not ever dream of subjecting it upon a beginner programmer.
Yes! Well that was the point of my comment. Maybe you have a different interpretation of 'Learnable as a first language' from the article, which is fine, not interested in arguing about that.
In logic programming it's known as the "generate and test" pattern, where you declare the tuple and the program logically generates all its possible values, and then tests each value for compliance. The runtime usually will ensure to make this in an efficient way.
P.S. See the definition of the "amb" operator in typical logic programming languages:
It's just more explaining, boring and driving people away.
My university taught Haskell as its intro language to math and science students, and the people who had the most problems where those who already knew a bit of programming. People for whom Haskell genuinely was their first introduction to a programming language on the whole had no problem getting it. I imagine this might be the same.
The main downside with the approach was that when these people who had just learnt Haskell moved on to the next programming course, that was taught using Java, they had a really hard time understanding what was going on.
Transactionality. Check. ACID type semantics are absolutely key to handling the concurrency issues created by a world with thousands of authors/programmers and concurrent actions. This is not the place for locks.
Declarative. Essential. This is going to be the only way to manage the complexity of interactions on a large scale. Though perhaps I don't jibe with the particular form described here and would instead encourage a more relational/datalog type approach, but that's my bias.
And management of mutable state / side-effects, through functional type approaches also seems key. Not just for expressing problems elegantly, but also for security / visibility management.
Some of the interesting things in here (approach to truth values etc) have a vibe similar to the approaches behind evaluation in a Datalog but also look similar in spirit to some of what's behind my employer's (RelationalAI) knowledge management programming language, Rel: https://docs.relational.ai/rel/primer/overview
Finally, people saying it looks difficult to learn, I think that for many people working in this kind of environment... it could be their first programming language. So they don't come with the same baggage & expectations about what programming languages are. Back in the 80s and 90s there were all sorts of "game builder" (esp for interactive fiction) type languages that often had what we'd now see as "odd" semantics. But this was part of the advantage. Heterodox approaches often bloom in domain specific locales.
Going to spend some more digging into this after dinner. Neat stuff.
“To answer "what does this program do, or what does it mean?“ just apply the rewrite rules.”
Whenever a senior engineer* uses the word "just" you're about to have a bad time.
* Or an expert in anything, really…
Can you walk us through where you think a language like Verse really shines with transactionality versus the current server authoritative models we see implemented in [language here] using [framework/pattern] here (like C++ and ECS)?
I've done my fair share of FP (got into Haskell years ago) so I see value here, but I'm not sure I'm grokking your level of excitement and would like to understand better.
Most programming languages I can least understand the general gist, the core motivation, whatever.
I have a lot of respect for Epic Games so I read through most of it but I have to say I'm still non the wiser.
If forced to summarize I'd say.. it's some kind of Haskell-ish language where the types themselves are defined by ... runtime functions? With some attempt at also being a prolog-ish logic language?
But why?
In a context where you want to have software built by different independent developer teams working on the same persistent world objects, you can't expect them to collaborate on programming style and coordinated libraries, as is done in industry software. Any unexpected side effect or variable aliasing in another library may ruin your runtime execution.
Pure functional programming avoid this by forbidding side effects, but forces a programming style where all state updates need to be declared and carefully handled by the developer. Functional reactive programming (spreadsheet-like updates) is being used a lot in the web to ease that problem (all popular frameworks have a version of it), but it is best suited to processing client/server updates, not full world simulations.
Verse approach seems to bring new expressive capacities suited for dataflow programming, allowing data transform logic to be built with functional expressions and separating these from the techniques needed to link one component to another.
I'm concerned about hoping "millions" of Metaverse devs will use Verse when, right now, the biggest problems with Metaverse are more about frameworks/netcode than the underlying language.
An open framework for handling interpolation, client & server space simulation (w/ physics), forecasting/prediction for events, and handling at least 30 ticks/s for a connection target with <150ms latency, <10% packet loss, while being able to handle thousands of connections + tens of thousands of entities PER instance (and also seamlessly mirror data across instances to enable large maps without zoning): that's a huge need for large-scale MMORPG-style Metaverse design.
I'm not at all certain we need a new language to do that.
I know it's hard to compare the usage percentage of various programming paradigms because many languages are multi-paradigm, but FP represents a much smaller piece of the pie (especially in games/networking) and, honestly, we have several generations of existing engineers who don't do FP.
Still, it's nice to see that Sweeney hasn't given up on making FP more useful to the mainstream! =)
"The aim is a transactional programming model with no visible networking or multithreading: you write normal code, and the system distributes the simulation across cores, servers, and servers by running updates speculatively, then committing or aborting them"
Seems vaguely similiar to how Unreal networking already works, but I guess more automatic.
Some parts of the game will perhaps have to run outside verse so they can be interpolated/smoothed, unless they have some magic to handle that also.
I fear this is a handwave.
What I mean by that is that its addressing the wrong problem for the Metaverse. Being able to implement an ECS model, for instance, where different platforms have common system requirements but because they're both built on Verse they can easily glom/reduce/map components and functions so entities in one ruleset can interact in the other... that's neat, but not a technology problem.
It's a combinatoric problem. And a game design problem.
By the time Verse is built up enough and has enough market penetration to try to take on this sort of role as a bedrock foundation layer for the Metaverse I think we're going to see two major shifts that make it obsolete:
1. The rise of AI-aided design and programming (think ChatGPT on steroids) that makes it pointless to worry about having One Great Solution when the AIs can just interop/translate and all the platforms (even competing corporate interests) can be "Metaversy" with their entities/players.
2. Either the combinatoric problem gets solved or it doesn't. Game designers have strong opinions on NFTs, for instance. The majority recognize them as incapable of solving the item portability problem (or as Raph Koster says, is it even desired?). Either novel ways emerge to do so and it's solvable, or they don't. I suspect either way the heavy lifting is not a programming technology problem, but a contractual/API one.
> By the time Verse is built up enough and has enough market penetration...
Verse will already have a dominant market position the minute you can do something in Fortnite with it.
I'm much more interested to know what the top LSL programmers or Minecraft modders think of it, than the team working on Guild Wars 2 or whatever. That's who it's relevant for.
I don't know if they have the wrong end of the stick. I'm afraid they might, because based on their presentations so far the Metaverse bit seems more tacked on than intrinsic. However, these are credentialed people well known in the field - it's hard to tell how much is exuberance re: Metaverse usage.
Regarding my comment on AI, I think it's relevant. It's not that AI will "solve all our problems", but that AI-aided design and code implementation will make learning a language like this obsolete. Transpilation will be seamless and backgroundy. So now there's a cost/benefit factor to learning a new language that was used to write a distributed execution layer for the Metaverse in a transaction-first manner, versus using tools that just "do it for us" and interact with the "product" created with Verse.
As far as Fortnite having a dominant market position once they do stuff with it, I'm not sure of that. I mean, StateScript being awesome doesn't make a dominant market position for it because of its use in Overwatch. I recognize the fundamental difference because the latter is closed and proprietary, sure, but I'm just not sure about the level of separation between Language and Product here when they're talking about the Metaverse. I look forward to learning more.
No, the fundamental difference is between Fornite and Overwatch, not between the languages. Fortnite has an order of magnitude more users and, more critically, is a freeform social gathering place in a way Overwatch is not.
Like honestly, I'm not sure you know what Fortnite is today, if you're comparing it with Overwatch. It's a competitor for VRChat and Minecraft as much as it is a Battle Royale game. This is going to make it a competitor for Roblox and Second Life too.
% Verse:
x:=(1|7|2); x+1
% Prolog:
foo(X, Y) :- (X = 1 ; X = 7 ; X = 2), Y is X + 1.
I think it might be nice to implement this language using Prolog. For example I think you could do the type definitions like this (let's ignore how :/2 is usually for module qualification): X:int :- freeze(X, integer(X)).
Kind of off-topic but I've always been curious why variable attributes aren't generally used for type-checking like this in Prolog.Anyway, very cool. I'll be keeping an eye on it. Is Epic Games hiring logic programmers? :)
One thing you can do in Prolog is build partial data structures: `X = tree(Left, Right)` builds a tree node with two "holes" `Left` and `Right` that you can fill in later -- or, crucially, might choose not to fill in. You can pass this "partial" data structure around, and other parts of the program may or may not instantiate it further. This allows some nice programming tricks. It allows proper tail calls in cases where functional programming doesn't allow tail calls, or only with heroic help from the compiler. It allows you to decompose your program in different ways from languages where you must always build data structures "inside out".
In contrast, Mercury is a syntactically Prolog-like language that doesn't allow this: (AFAIK) when you pass a term to a predicate, it must either be ground, i.e., without any leftover "holes", or a variable, i.e., completely uninstantiated. This throws away much of the power and convenience of Prolog. And any language that takes a pure "Prolog's logic variables are just sequence generators" approach must also fall into this category.
Verse seems to be more lenient in the "it's all just sequences" department. You can pass uninstantiated stuff into functions and have it further instantiated in there. It's not clear to me to what extent this works, there are no examples with data structures in the slides and I haven't gone through the paper yet. I can well imagine this being closer to Prolog than to Mercury. But the "Everything is eventually evaluated" is definitely not fully Prolog-like; Prolog doesn't care about everything eventually being ground. There is no need for that.
On a related note, even though it's popular to say that Prolog can "run code backwards", that is in fact not the case at all. Prolog always runs your code forwards. If your code is designed accordingly, you can often treat an argument `X` as an input and an argument `Y` as an output, and also have a use case of the same code where `Y` is an input and `X` is an output. But the code itself always runs in a well-defined top-to-bottom, left-to-right way. This is notably different in Mercury, where the compiler will explicitly compile different versions of your code for different use cases, reordering things so that sometimes you are actually running bottom-to-top when compared with the source code order.
Evaluation order in Verse is... all over the place. I suspect this will be problematic in practice. If you understand how Prolog evaluates your code, you can work with it to write performant code. Verse seems to be too flexible in this regard, so that it will be difficult to impossible to understand what is actually going on in what order. If you treat all your values as generators that can start enumerating stuff at any point, it will be very easy to have cases of combinatorial explosion by choosing wrong orderings. I see that there are some notes on this in the paper, but not much more than "some things are obviously not what we want, but we don't know what exactly we want". So let's see what happens, but for now this doesn't seem to want to be close to Prolog.
Final syntactic notes: Mercury has the Prolog-like predicate syntax that as noted can run "backwards". It also has a functional syntax where (AFAIK) it's not possible to run "backwards". This seems to be the right choice to me. You can mix and match predicates and functions to build what you want and retain clarity. Using a function syntax for things that can run "backwards" will be cute but confusing. Relations should be written as relations IMHO.
As for micro-syntax, others have complained about `fst` and `snd`, and I also tend to think that we can afford a few more bytes. But my main complaint is with `false?`. If in the slides introducing your syntax you feel compelled to call something "quirky", that's a clear indication that it should change. It's such a weird name. Why the question mark? Why does the name evoke booleans if the language has no booleans and discourages boolean thinking? If I'm supposed to think in terms of sequences, a better way for a sequence that contains nothing would be `none`. If I'm supposed to think in terms of logic variables, a better name for a logic variable that is bound to no value is... also `none`. The name `false` is just such a surprisingly bad fit.
This is something to watch, it's an interesting point in the design space. It might end up as something that (finally) is better than Prolog. It won't end up as being "almost the same thing" though, I don't think.
What do you mean? The actual "computational" part of Prolog lies more in resolution than in unification. Unification does not "evaluate" in any sense of the word I'm familiar with.
> the same prolog programs can at least theoretically produce two different answers to the same input.
What do you mean? Do you mean through side effects, or are you suggesting that Prolog's evaluation order or something else is not fully specified and deterministic? You would be wrong about the latter.
EDIT:
> Verse has a defined denotational semantics
What do you mean? Verse (or rather the underlying calculus VC) has a rewrite semantics. Rewriting is pretty operational and not at all denotational.
Slide 61 and 63 hint at things that might actually be of consequence to real programmers making real software for a potentially real metaverse, such as the effect system for I/O, transactional memory and code organisation through classes and inheritance, but it gives no detail.
If you're interested how elegantly functions like head, tail, cons, snoc, append and map might be implemented, this presentation is for you. If you're more interested in how you might unpack a message from bytestring, model a state machine or coordinate a group of actors in a distributed system, then I guess you'll have to wait for the next presentation.
The "View from 100,000 feet" slide does highlight the kind of experience SPJ would have in identifying where Haskell lacks a bit in pragmatism as a basis for a new, but not super different language. Hopefully the tooling is much better though.
It was presented at Haskell eXchange so the audience is more like Haskell users in industry and those who would like to be.
(My first reaction is some slight aversion to what the "flexible" and "rigid" stuff is doing in the conditional scrutinee body, but maybe that'll feel natural after playing with the formal specification a bit.)
I really liked Oz, and thought it had a lot of potential. But its documentation was a big adoption barrier (scattered mess plus expensive textbook), and Oz failed to escape being a turn-of-the-century European research and intro-CS language. The intro-CS role perhaps lends plausibility to Verse's "a first language" objective, despite the off-mainstream computation model. Explicit `amb` though.
[1] https://en.wikipedia.org/wiki/Oz_(programming_language) [2] http://mozart2.org/mozart-v1/doc-1.4.0/tutorial/index.html
I want to take a moment to look at the Metaverse angle. If there is going to be a unique programming language for the metaverse, I think it's not going to be textual but instead is going to primarily be a 3D language. This poses a big challenge for a VR language because text is great[1]. The point of making it 3D would be that you are somehow capable of transmitting more information via the higher-bandwidth channel of the human visual cortex than you are through text.
If you aren't making a 3D programming language, well then it might be a cool programming language but I don't know what it has to do with the metaverse.
Hopefully we'll get more useful info soon, once it can be used in Fortnite.
Speak for yourself! I got a lot from it that feels immediately practical for my current projects as well as others I want to take on, and it makes logic programming concepts and benefits much more accessible to me than any amount of Prolog literature has so far (granted I came in wanting to be compelled).
I'm approaching it from the angle that I don't see how functional programming is at all useful for the kind of gameplay programming that would be done in a "metaverse" or is done in Unreal Engine today. So "it can do functional programming stuff" by itself doesn't cause any excitement. Rather the opposite. There are zero code examples of using it for anything besides abstract math. It executing code out of order seems to serve no purpose besides letting people create undecipherable monstrosities with it.
I'd maybe sum up this presentation as "we took functional programming and tried to make it less unusable by letting you actually mutate state" but I'm still lacking the original motivation of why I'd want to use that in the first place.
- null safety
- deferred evaluation of expressions with unresolved dependencies
- types as first class values
- the real thing functional programming is about: making it possible to know what value is bound to a thing at any point in a program
The first is valuable for any program, the last is valuable for any program with multiple inputs (so, games, but also basically any human facing program because IO, or really just any program with users and real world interfaces), and types as values is a world of oysters if you like what types afford for development.
Edit: lol I forgot to expand on deferred evaluation, it’s a really good model for distributed users but could also be a good model for highly dynamic applications like one I maintain where there’s a hard constraint on synchronous execution but currently a very lazy model of what needs to be executed.
For instance this might be super mario... mario moves forward or the gumba moves forward or mario hits the gumba and mario enters death animation and the gumba stops or mario hits the gumba from above and the gumba enters death animation or mario hits a coin box and a his coins increase and mario stops and the box enters coin animation.
Verse and the metaverse were ideas at Epic Games long before SPJ was an employee at Epic games (at least 10 years before).
I'm hoping they'll upload a video soon, which'll probably be a lot more fun than slides. They've only got the recording up for one of this year's talks so far.
https://skillsmatter.com/conferences/13688-haskell-exchange-...
[1] https://simon.peytonjones.org/verse-calculus/ [2] https://simon.peytonjones.org/assets/pdfs/verse-conf.pdf
The big idea I see is that prolog-style backtracking logic becomes a first class notion in the language – every expression denotes a sequence of values reached through backtracking-like behaviour – which allows mixing logic-programming with a more familiar kind of functional programming. Though perhaps there are other ideas too.
I think it will be interesting to see where this goes. Perhaps this will be another Fortress but SPJ is well regarded, has written a bunch of interesting papers, and has a bunch of experience managing a programming language project from haskell which will hopefully carry over.
The metaverse things used to motivate this language don’t seem new to me either. Aren’t they basically ‘works well with concurrency’ and ‘somehow the language that finally makes it easy for different programs written by different people to talk to each other’ which don’t seem to be new goals in programming language design as far as I’m aware. But maybe I’m being uncharitable in my interpretation.
I’ve not looked at the associated paper or tried to understand what the metaverse is so maybe things are better discussed there. Or maybe they are glossed over because the presentation was for PLT people rather than metaverse people and I think many of the former would be turned off by a talk about the metaverse.
This doesn’t strike me as a very serious attempt to predict the future and design a programming language based on that prediction (though few such attempts exist for the design of most things in tech, and they needn’t correspond to success). It seems more like taking a punt and exploring a new point in the programming language design space that may be relevant.
I think it is interesting to look at what happened with Fortress for comparison:
- Well known PLT person (Guy Steele of scheme, CL, Java fame) in a reasonably funded industrial research lab
- they started with ideas about where computers were going around 20 years ago. So high core counts, big memory vs cpu frequency divergence, NUMA/HPC architectures. And an increasingly difficult amount of legacy Fortran code
- developed an idea for a language that would be easier to write parallel scientific programs in
- eg functional, map-reduce paradigm
- added in some known features like typeclasses (monads for map reduce)
- some other random features/ideas
- wrote a bunch of papers
- not that much actually came of it, I think
Maybe they weren’t good at executing on making a language people wanted, or maybe that was never the goal. Or maybe they were too early – a lot of the ideas became more important with gpu compute but most people still write those programs at a much lower level.
Some of the influence is quite conscious, too, from my reading. Though as you mention is obviously a lot of common influence from Dylan and Common Lisp.
And here's a talk by Guy Steele about the Fortress experience, at JuliaCon:
I don't think it is trying to predict, it is purpose built to be the Unreal engine scripting language. I hate the word metaverse, but it will be a highly relevant, important language to online multiplayer worlds as soon as it is released (as soon as a month from now).
For what it's worth, Tim Sweeney (the "boss" in this story) has been thinking about Verse or something like it since at least 2006: https://www.st.cs.uni-saarland.de/edu/seminare/2005/advanced...
It seems much less like SPJ getting funding from a big-bucks metaverse boss, and much more like Tim Sweeney getting together a dream team to make his dream language in one form or another.
I wouldn't take your skepticism as uncharitable as much as realistic. If a company is trying to apply some abstract theory to solve a problem, they might hire a theoretician to work on it. They'll say "We are advancing X theory to solve Y problem for our customers". Well, the "we" in there is one dude and his motivation certainly isn't Y. He'd be working on X regardless. Y is just the reason he's getting paid. That's not exactly what's going on here, just sayin distorted motivations aren't that rare or even really that nefarious.
On the not-newness, I think that's true, too. You can justify it by saying that a metaverse will have the same problems in different proportions. This would justify approaches with tradeoffs that wouldn't make sense in other situations. It looks like it's optimizing for a system with high concurrency, weak coordination and on one platform. So like Erlang at Ericsson but more programmers, or like the internet but less independent.
Thank you for sharing the Fortress example!
In verse `=` is unification and not assignment or comparison. Meaning its a constraint on the lhs and rhs. Unification is also an expression meaning it can be normalized to a value e.g. `x=3` normalizes to `3`
Expressions can be sequenced with `;` but note this is nothing like imperative programming due to unification. These sequences normalize to the last expression in the sequence but the unifications in all subexpressions apply to the whole sequence. Thus `=` appearing in subexpressions in any order does not change the resulting value (since the compiler uses normalization)
Now functions can be seen as lambdas or anonymous functions to these sequences of expressions where the arguments are also constraints! These functions themselves are values. Thus functions are first class.
Another key aspect of unification is that functions can run backwards. Thus `swap<1,2>` will return `<2,1>. But so will `swap(p) = <1,2>` constrain `p` to `<2,1>. Thus the meaning of function is no longer just a procedure. But more of a specification or constraint.
And this is exactly what types are in Verse. Types are functions thus first class. When we say `i : Int` it is akin to saying `Int(i)` constraining the variable `i` based on the constraint `Int`.
Thus if you have a function that succeeds when given an even number, that function can be seen as a type of even numbers.
I highly recommend the book “Type Driven Development” if you want a great introduction to the power of DT.
Sure you can have terms in types in dependent types; thus functions in types is nothing new. But again, we have a much different notion of function here.
And if anything I would say types in Verse are much closer to refinement types because of its ability to apply constraints. But they are still not the same thing.
As of now all we have is a core language. But its not hard to read between the lines to anticipate how powerful it can be so that features that the industry needs can be built upon it.
I see the issue is that iff you explicitly marked it as inout, it would limit the code from a logic unification point of view. I guess this is already explored in prolog, which I have little experience with - but it feels like it would inherently limit the ability to scale a codebase to huge sizes. Maybe a combination of convention and naming would solve the problem.
The distinction between bringing variables into scope and assigning them values is a strange one for a functional language, but in fairness the talk is titled beyond functional programming.
https://mobile.twitter.com/saji8k/status/1339709691564179464...
I believe it has roots in (but quite different from) Skookumscript
The screenshot says "BoxFight.verse". Either Unreal has two separate new programming languages both called Verse, or you're plain wrong.
The screenshot you linked to shows boolean variables being defined ("bool") while the new SPJ language being discussed here very conspicuously lacks a boolean type. That fact alone is enough to convince me that there is an "old", less cool, less ambitious Verse language, with different syntax etc. which is about to be replaced by (or as Tim says in tweet, get "converged with") the new SPJ Verse.
They apparently like the name/branding so much that they want to keep using it, even though the fundamental principles of the language are going to be different. That does seem potentially confusing but it's their business. After all, the old verse never got released to the public.
So it seems totally clear to me that a previous, less complex and ambitious, scripting language called "verse", which has been around for a while and never really gone anywhere, is going to be replaced by the new SPJ functional language "verse".
> We're more than a year away from an open source implementation that's converged with what's in Fortnite. In 2023 we'll be giving lots of talks and likely releasing some of the research pieces.
https://mobile.twitter.com/TimSweeneyEpic/status/15955006213...
https://mobile.twitter.com/TimSweeneyEpic/status/16021821207...
You can find more information here: https://www.reddit.com/r/uefn/
I believe they've been using Fortnite as a testing ground for a while now, to hammer out the design.
But just because they all did it (and most before web searched existed) doesn't mean future languages should.
I understand this is a pet project for these folks but I think that a metaverse grammar should not fe functional but procedural - it should be extremely simple and accessible to novices. We want these tools to be accessible to everybody I think - unless we as programmers want to be responsible for building all interactions for all users.
But I mostly think a grammar today isn’t just about the literal parser - instead it is more about the parser and surrounding tooling. Rust for example is surrounded by tooling that helps - cargo/crates are a nice helpful way to make rust developers effective.
If I was going to devote significant energy to this topic I’d solve other problems. Any code that users write needs to be late binding - allow software agents to be pushed to the cloud and participate in already running simulations or models. Code should allows users to define granular security around libraries and components to prevent them from doing bad things. Code should be highly portable; able to run across many devices at speed - not something new that has low cross platform support.
I think a better way of thinking about this isn’t the grammar itself but the kind of “computational sandbox” one is offering - the grammar container or app runner.
WASM is a good example of thinking in a better way - portable, secure, performant. It’s more like a metaverse tool than the above grammar.
What’s especially curious to me is that Tim’s project Unreal is almost the anti-metaverse. It is utterly fixated on and built around an extremely heavy high fidelity renderer - that is not portable - that does not run across many devices. Unreal uses an old school compilation philosophy that requires behaviors to be precompiled - so if you want to add a single feature you have to tear down all the instances, recompile them, recompile the server too, distribute a new build to all participants and restart the sim. It’s a tool designed for a different era and a different ecosystem… in a sense AAA games are the opposite of a participatory constantly evolving online shares consensual world. So maybe he should fix that first.
This is doing unreal engine a significant disservice. Unreal is significantly more than a high fidelity renderer; Unreal's replication system is excellent, as is the gameplay ability system. (To my knowledge, neither of those systems exist in any of the other major engines that are readily available). There's a laundry list of things it does pretty well,distilling it down to a renderer only is very dismissive.
> that is not portable - that does not run across many devices.
Renderers by definition aren't going to be portable, they're pretty intrinsically tied to the hardware (and OS) they're running on. Also it's silly to say it doest run on many devices - it runs in every games console for the last decade, an enormous amount of mobile devices on both android and iOS, and on all major desktop platforms natively. What more do you want?
> Unreal uses an old school compilation philosophy... So maybe he should fix that first.
Unreal definitely has some dated design decisions that are showing their age, but that's to be expected for a codebase that's 25 years old. And if you've been paying attention to what epic are doing over the past few years you would see they are working on that.
(Disclaimer: I worked for epic until recently on exactly the things you're talking about in this comment)
[0] https://www.microsoft.com/en-us/research/publication/tacklin...
source: https://graphicdesign.stackexchange.com/questions/38226/what...
[0]: https://www.edutopia.org/article/do-dyslexia-fonts-actually-...
a good phrase on this link: "... dyslexia is a language-based processing difference, not a vision problem, despite the popular and enduring misconceptions."
It’s one of the reasons I like him, zero ego but still a genius. It’s the opposite of McKinsley (zero substance but looks great).
Neither the prospect of spending time in the "metaverse" for "social interactions" nor a language design that requires you to keep in your head not just simple bindings to names but sequences of values, is just not very appealing.
What are younger folks thinking how they will be interacting with the metaverse? Less clunky VR glasses you can wear for more than an hour?
The problem with SQL's NULL are its properties (comparison and arithmetic in particular), which doesn't seem to apply here (e.g. "42 + false? === false?, just as with monadic function composition and Maybe monads).
> The problem with SQL's NULL are its properties (comparison and arithmetic in particular) [...]
Which I follow, then you say that those unfortunate properties don't apply and give a counterexample (I think it is intended as a counterexample) of
> 42 + false? === false?
But that seems to be the same as SQL's NULL:
benji=# \pset null NULL
Null display is "NULL".
benji=# select 1 + NULL;
?column?
----------
NULL
(1 row)
Which leaves me confused.Consider a column with values (10, 20, NULL, 30).
In SQL the AVG() function would return 20, i.e. ignoring the NULL value entirely. COUNT(*) on a table, however, would happily include NULL values, whereas COUNT(col_name) wouldn't. The behaviour is all over the place, especially when different dialects and settings are considered.
This doesn't present any examples of something that would be useful in the real world. But come-on, this was presented at a Haskell conference it looks like.
For anybody with an interest in the "mathish" flavor of functional languages, this certainly has a lot of promise as a foundation to build on.
(< 1 2 3 4 5 6) => true
Aren't these companies pursuing a "metaverse" product because they can lock it down, control it and make money on it? Otherwise rather than FB and Epic etc making their own, you'd have something developers could work with and use right now
I wonder if maybe Simon Peyton-Jones has to play along with the whole metaverse fad just to do something he wants to do.
Look at the open ecosystem of the web and think about how much money ICANN and Verisign make from their DNS. Anyone can make their own independent DNS (see projects like namecoin), but ICANN's has a big first mover's advantage that makes it hard to compete with them.
That goes all the way down to DNS and connecting a server to the internet in the first place.
ICANN and IANA allow you to have a name and IP address, but you pay a middleman extra (in many cases a whole lot extra) for those because ICANN and IANA don't want to deal with you directly so you do it they way they want you to.
Amazon/Microsoft/Google allow you to have server time and hard drive space, you buy from them because servers are super expensive...because they bought up all the servers and continue to do so.
Also you can't run a server at home anyway because the company that bought the rights to lay network cable in your town/county/city doesn't allow you to.
You might be able to run a server anyway if you buy or rent an office in one of the locations they serve business internet to, but you'll run it they way they allow, for the uses they allow, at the speeds they allow, and you'll pay a lot for it.
If you want to self publish, even with a basic site you probably use Wordpress or something similar because the existence of design platforms has raised the public's expectations for what a site should look like and be able to do. So you design your site the way the design companies allow you to.
If all that's too much and you're just looking to write stuff for people to read on the internet, you most likely use Medium or Substack or something similar. And to do so you agree to their terms of service and end up discovering what gets attention and what gets ignored on that platform. So instead of writing what you want per se, you write what they allow you to.
If you want to share video content, you do it the way YouTube wants people to, right down to reminding people to like and subscribe and hit the bell, in every damn video.
If you want to share your love of crafts, you use Etsy. If you want to sell stuff generally, Amazon again. In both cases, you follow their encyclopedic sets of rules about what and how to sell as well as their convoluted, ever changing, unpublished rules around what shows up where on the listings and searches.
If you want to connect with people, you connect how and to whom Facebook or Tiktok allow you to.
If all this pisses you off and you want to rage at random people, you rage about the things Twitter allows you to.
In theory anyone can do any of those things without the platforms, of course, but in practice they don't and always for a slew of reasons that basically amount to someone got here first and built a moat.
In the most basic cases, anyone trying to do something on their own will at least need to advertise...on the platforms, the way Google, Facebook, and TikTok allow you to. Good luck.
To this day I have still never really "got it". From what I can see, the people who love it really do love it, maybe one day I'll give learning it another shot.
In what respect is it an advance? It seems to me strictly less expressive. (Which is not meant as a denigration; this design seems well suited to the problems it is trying to solve.)
Also, I appreciate how a bunch of new languages are getting Effect Systems (Unison, saw that one here too)
It's 2022 and he's still very very relevant in the gaming world. He still runs Epic, he's still publishing papers on gaming. I don't think any of the other folks from that early era of PC gaming are still relevant in the field (Carmack moved on to VR and now AGI).
It seems to me that the objective is not finding a good language for a metaverse, but using the idea of a metaverse to justify this new language.
More realistically, an open metaverse (if it will see existence, I'm not yet convinced of its utility) will support multiple languages.
Even more realistically, the internet is a metaverse already.
(I'm pretty sure that's not what is discussed in these slides...)
A functional language has some advantages - because Winter programs can be bounded in space and time, we can efficiently execute untrusted scripts from users safely. The scope of Winter programs is reasonably narrow - mostly pretty simple scripts setting a transformation as a function of time. But for that it works well.
The bit-identical virtual machine is pretty nice idea. I hope to see some demos for WebXR soon.
I’ve done some game programming software and a large number of their decisions make sense in that environment. In particular, expression evaluation and a lack of booleans.
Other than that I like a galactic scale transactional memory and trying to make Haskell simpler for the masses while still supporting professional programmers.
I worked hard to understand the slides (BTW, I am an enthusiastic but not skilled Haskell programmer) and in 6 months or so when they drop ShipVerse I wonder how much I will remember.
- What's the advantage of introducing a new lambda calculus extension? What will we understand about Verse in virtue of the existence of VC that we don't understand about e.g. minikanren?
- How does the rewriting based execution compare with the search procedures of existing logic programming systems, and how does that impact how one would use Verse? For example, it sounds like they both want Verse to be purely declarative and performant enough to support the metaverse. But:
- The way the slides expand out the choice of two variables makes it look like it's working in DFS order. The paper makes a big point of rewriting expanding out values "spatially" rather than in time. And I guess it's relatively clear how the rewriting system would produce DFS-like behavior ... but that's a problem isn't it?
- E.g. minikanren as one of its key design points chose its interleaved search so that search could give comprehensive results on problems where DFS would (naively) never return, because it would go down some infinite rabbit hole. And minikanren, wanting to be more declarative, doesn't rely on "extra-relational" operators like "cut" which are important for prolog. This was supposed to have the impact that users don't need to worry about imperatively controlling the search, but this is only half-true in that users must pick the order in which variables are introduced extremely carefully.
So if one says "x, y, z are all nats in (0, 1, ...) and x * x + y * y == z * z", it seems that, as with DFS, the rewrite system would include a path which tries to expand out and then check all of the (0, 0, z) possibilities to the left of any of all of the (0, 1, z) possibilities, etc. So even if under lenient evaluation there's _some_ tree that finds (3, 4, 5), and this may be reached in chronologically finite time, there's an infinite pile of work to be evaluated _to its left_. So can one never take the "first" element from this sequence, since it seems this means "left-most"? Or does this whole thing need to implicitly be restricted to searches over finite domains?
It seems like either one must loosen assurances of ordering within sequences, or one must include "extra-logical" means to control the rewrite process.x:int; y:int; if (x=0) then y=1 else y=2; x=7; y
Ok, so here, y=2. And then it goes on to say that the equal operator within a "conditional scrutinee" is "rigid" and can only be read, not unified. Does that mean if we take out the "x=7;" line, and then evaluate "y", that "y=(2|7)"? Or how exactly does that evaluate?
When evaluated, the "if" expression is added to the "knowledge store", so that it will be evaluated when "x" is bound elsewhere, giving "y" the corresponding value (just "1" or just "2", never "(1|2)") only after that.
P.S. See the definition of the "amb" operator in typical logic programming languages:
Yet this presentation did none of that. There were no montivating examples on practical usage. The language does not map cleanly to webassembly, it instead reduces to a prolog like graph based execution model. In order to go mainstream you need to be solving more problems that existing languages have than you are creating by having someone use your new language.
A webserver serves document while a metaverse server is basically a multiplayer videogame host.
Your browser opens a metaverse site by downloading a game engine and running it through JS and fetches the resources from the server to load the 3D environments.
All this to say: what has this functional programming language actually to do with the metaverse?
That said, I’ve worked with a few of the Haskell OG team (not directly SPJ though) and if you bring in a functional language designer to work on a project you can bet it’ll start with a new language (I’ve worked on two domain specific languages due to this).
Some of the constraints right now with this sort of program are CPU/GPU bound, so if we they’re building a new I suspect it’s going to focus on concurrency across threads/GPUs to support the high rendering requirements etc and make it easier to work with networking and C/C++ FFI GPU drivers. This is speculation on my part though :)
How ? I can't see anything in here that makes these worlds any easier to drive.
I think concurrency is more of an issue for games and was the example I gave (Haskell's transactional memory for concurrency is a great example of what pure-functional buys you). Nethertheless autoparallism can work, if you again are prepared to accept more constrained declarative languages. Apache Spark is a great example, it offers a constrained functional language with maps and folds, that is autoparallized across a cluster of machines. The research language NESL (nested data parallelism) is even more impressive.
The longer answer is pure functions applied to immutable objects (or objects held in a transition) can be applied in parallel.
The language is designed in a way to give you that, in a way where it is by default rather than in special cases.
The second part is, it being at a mid point between lazy and not - things will be evaluated as there is processor to do so. So things which can be delayed will be, but if something can be done now, for later, it will be.
The combo of this means you can handle more interactions with entities per second, using the cores available.
I have been writing code like this every day using Scala for years.
With frameworks like ZIO (zio.dev) making this trivial to do.
None of which is faster than if I had wrote that code imperatively using say Java. It is definitely easier and safer to write. But performance is about far more than just optimised threading constructs on top of immutable data structures.
Perhaps it would be better for the team to work on a runtime environment (think JVM or similar) optimized for the metaverse. With compilers for a number of languages compiling to it.
So, not a variable? :)
':=' is didactically better because it shows that assignment has an direction. It also leaves '=' for actual equality.
If we somehow happen to have a few competing metaverses, the one with the biggest developer mind share will likely come out ahead.
Just reading the PDF energized me about the possibilities.
I am equally surprised by the novelty that some people seem to have when encountering this language. As far as I can tell, nothing of real novelty was added to the corpus of PL knowledge. It's really a straightforwards logic language. These are notoriously hard to program in for one person, especially when things get interesting (i.e. cuts). I can only imagine how awful such a thing will be if multiple people were doing this.
The sequence and narrowing stuff looks super interesting though!
How does x:=(y|2); y:=(7|8); (x|y) Give only (7,7), (8,8), (2,7), (2,8)?
What about (7,8) or (8,7)?
By that logic, how is either (7,7) or (8,8) allowed?
translates (roughly) to:
(x|y) is a cartesian product--the set of all ordered pairs (X,Y) such that X is in x and Y is in Y, in order.
x has 2 elements: X=y and X=2.
y has 2 elements: Y=7 and Y=8.
So the set of all ordered pairs is (X=Y, Y=7), (X=Y, Y=8), (X=2, Y=7), (X=2,Y=8).
Since X=Y in the first two pairs, replace it with the value of Y from that pair: (X=7,Y=7), (X=8,Y=8).
If x = 2 then clearly (x, y) is not (7, 8) or (8, 7) because 2 is not 7 or 8.
If x = y then (x, y) is (7, 7) or (8, 8).
My personal preference for a typeface that gives off the feeling of handwriting is an italic one. Palatino's italic bold is quite nice for that.
Pretty much. Simon Peyton Jones has used for years, and if I recall correctly, he said that he just likes it, for whatever reason.
It is not a functional language and is obviously quite cheesy in comparison (see someone's comment, in this thread, about it being derived from something called skoomumscript).
SPJ's language is not ready yet.
:)