1. 33
  1.  

  2. 12

    There’s a lot of good stuff here, effects, transactional memory, a concurrency story without colored functions (don’t be fooled by the documentation mentioning async over and over, it’s different stuff), a completely novel way of dealing with failure, planet-scale repl (not yet available), etc.

    But I feel like they had a list of features and a specific syntax that they wanted to give to game developers, and they then had to shoehorn “the good bits” (the semantics) into these arbitrary features. Some things are truly bafling, like it has both significant indentation and {}, at programmer’s choice. Wat.

    Also I think the documentation is not great. It says reference in the title, but as a reference is not very thorough, in fact it’s more like a tutorial, but the sequencing is not very pedagogical to be a tutorial either. In general the concepts are explained at a very basic level, but then sometimes it throws very technical concepts at you out of the blue, like type polarity. Also a lot of the links are 404 and they hijacked middle click. Ugh. They also publish memes in the documentation. In fact all images published as part of the documentation are kinda pointless.

    I suppose I’m not the target user here, but I really wish there was a way to play with the language outside the Unreal editor. Surely this has to be possible, if anything, just for their own developing team’s sanity. (Edit: after watching the video linked at the bottom of my post, apparently this is coming, they are going to release it as open source!)

    In any case, I am really excited about this new language, quirks at all, and I am really waiting for the next papers the team will publish. The first paper was really great!

    Edit: there’s a quick video presentation: https://youtu.be/teTroOAGZjM?t=22512

    1. 5

      More thoughts.

      Notice how the naming convention is for values to be Capitalized, while types and functions are not. My prediction is that this is because types in Verse will be just (failable?) functions that validate values.

      I said failable above, but they might be some other kind of functions. They have a total effect type (functions that are guaranteed to terminate), which could be safely called by the type checker.

      In fact I think that class and other constructs are some sort of compile-time macro. I suspect some syntactic idiosyncrasies are about making the language homoiconic.

      Verse has effects, but not algebraic effects. The set of effects is finite and fixed, and there’s no way to define arbitrary handlers. All effect processing happens in language constructs like if and for (which might be macros, so maybe there will still be some user-level support for handlers after all). Because it does not have a full blown effect system, concurrency and monadic composition had to be baked into the language, with an effect system these features could have been implemented in a library instead.

      Notice how effects are negative types. They are a promise about what a function will not do, not an indication about what a function might do. This is the opposite of other languages with effects.

      defer is not needed if you have linear types. I suspect they considered linear types too difficult for the average programmer, so they went with what they consider a good-enough solution.

      The type system is probably very novel, I suspect it is the most interesting part of Verse but so far has not been explained or talked about at all. I suspect it might have some form of dependent types.

      1. 1

        A curious thing I found in the API reference: https://dev.epicgames.com/documentation/en-us/uefn/verse-api/versedotorg/verse

        As far as I can tell, specifiers like <abstract> and <transacts> are all real types. Weird, huh? Almost as if they planned arbitrarily defined effects from the start, just don’t document them.

        1. 1

          Very interesting. Maybe there are arbitrary effects after all. Seeing them documented this way kind of reminds me of Haskell type classes. Maybe what you put in the function specifier are instances of a specific type class, and the compiler somehow calls into it at compile time to verify your code.

      2. 2

        like it has both significant indentation and {}, at programmer’s choice. Wat.

        Isn’t that what Haskell has?

        1. 3

          Yes. Also wat.

        2. 2

          Some things are truly bafling, like it has both significant indentation and {}, at programmer’s choice. Wat.

          Not surprising, since Haskell has the same feature, and Verse is designed by some of the original designers of Haskell.

          1. 2

            And they added commenting by indentation!

        3. 6

          I’m feeling some cognitive dissonance between “friendly beginner language for scripting FortNite” and “innovative post-functional language with a bunch of powerful but weird features.” I found a slide deck by Peyton-Jones (set in Comic Sans?!) and halfway through I’m getting confused by variables bound to series of values, and “narrowing”…

          1. 7

            You’d be surprised by how quick people can pick up concepts without any preconceptions. I’d be really curious if we see some sort of Fortnite mod to functional programmer pipeline.

          2. 3

            Highly recommend this video by Simon Peyton Jones which goes into may details missing from the reference: https://www.youtube.com/watch?v=832JF1o7Ck8

            1. 2

              One thing I personally wonder about is the compiler - how fast it is and how good the error messages are. Epic doesn’t have a very good track record with that 😅

              • UnrealScript was quite slow to compile, and the error messages weren’t particularly helpful.
              • Neither is Blueprint particularly fast to compile, although it’s at least two orders of magnitude better. The error messages leave a lot to be desired though.

              I like the language design a lot though. I’m implementing an UnrealScript compiler, and the amount keywords you have to churn through is astounding. Good that they solved it with a unified @annotation and <specifier> syntax.

              As a compiler developer, it seems weird to me that parametric types have the limitations they do (particularly the fact you can’t use them in vars.) Smells of the compiler being quite jank to me, but I haven’t seen the source code so no clue 😄

              I like that they are continuing the legacy of UDK with UEFN/Verse. I’m excited to see what the community will build using the tools.

              1. 4

                As a compiler developer, it seems weird to me that parametric types have the limitations they do (particularly the fact you can’t use them in vars.)

                As another compiler developer, I suspect this is probably due to something similar to this in ML-derived languages: https://v2.ocaml.org/manual/polymorphism.html#s%3Aweak-polymorphism

                1. 3

                  I suspect that it’s due to the quasi-relational behavior that they’re working with; I remember Wadler explaining that type annotations are actually predicates which guard annotated variables, and that they are resolved relationally along with all of the other variable-unifying behaviors.

                2. 1

                  It sounds cool, but I can’t find any code! I clicked around a bit but couldn’t see any examples of real-world code (a hundred or so lines at least of actual non-example game logic) - am I just being blind/lazy?

                  1. 1

                    There are quite a lot of examples, I managed to fing them at some point, but the documentation is so badly put together I can’t find them anymore even knowing they exist!

                  2. 1

                    Further to @4ad’s comments, I’m finding the docs very peculiar:

                    In all cases, calling a function that has a specific effect will require the caller to have that effect as well.

                    So calling a <converges> requires the caller to be <converges>? That doesn’t quite seem right. I feel like they want to say the opposite: if you’re <converges>, it’s not the case that your caller is required to be <converges> (i.e. you may call sin() from a function that also does non-deterministic things); rather, if you are, your callee must be (i.e. your sin() implementation isn’t allowed to invoke the network or not terminate).Otherwise no <converges> results would make their way to non-convergent code.

                    And yeah, wow, the images really don’t fit.

                    1. 2

                      Oh, okay, now I’m really getting the “negative types” thing — this statement of theirs actually rings true if you negate the effect concepts in your head first: if the effect is instead called “non-convergent”, then obviously to call a non-convergent function you yourself can’t have promised to be convergent, and must instead “have” the non-convergent effect.

                    2. 1

                      I can’t find any mention of the choice operator described in https://simon.peytonjones.org/assets/pdfs/haskell-exchange-22.pdf