[HN Gopher] Dada, an experimental new programming language
___________________________________________________________________
Dada, an experimental new programming language
Author : marionauta
Score : 377 points
Date : 2024-03-06 10:31 UTC (12 hours ago)
(HTM) web link (dada-lang.org)
(TXT) w3m dump (dada-lang.org)
| brabel wrote:
| If the claim that its performance will be similar to Rust's if
| you add type annotations, this could become a really attractive
| language!
|
| As easy as JavaScript to write, as fast as Rust when the extra
| effort to write it justifies it.
| wokwokwok wrote:
| There's no claim to be as easy as javascript to write.
|
| Rusts "difficulty" stems from its single ownership model, and
| this model is "different" not "easier".
|
| https://dada-lang.org/docs/dyn_tutorial/permissions
| rubyfan wrote:
| From what it looks more expressive and seems intuitive to me.
| DinaCoder99 wrote:
| I personally find the semantics of javascript a lot harder to
| internalize than rust due to its scoping and very unintuitive
| object system. I can't imagine this is any more difficult
| than that.
| jokethrowaway wrote:
| I agree but most modern JS doesn't use prototypal
| inheritance.
|
| JS has plenty of bad parts you shouldn't use. Classes are
| the main one.
| iopq wrote:
| I had a coworker who wrote return
| { ... }
|
| And JS helpfully inserted a semi-colon after return
|
| This is a feature you need to know about and you have to
| go out of your way not to get rekt by it
| usrusr wrote:
| Still super weird, because the garbage collector tax that is
| avoided by the borrow checker that's decidedly _not_ gone isn
| 't all that big to begin with.
|
| But perhaps it's a viable "training wheels" approach for
| getting used to borrow-checker friendly patterns? And I guess a
| scripting interpreter option that is fully rust-aware in terms
| of lifetimes could be truly golden for certain use cases, even
| if it turns out to be completely hostile to users not fully in
| tune with the underlying Rust. Sometimes "no recompile" is very
| important.
|
| I wonder if the genesis story of the project might be hidden in
| "Dada has a required runtime": perhaps it started with the
| what-if of "how nice could we make Rust if we abandoned our
| strict "no runtime!" stance and went for making it runtime-
| heavy like e.g. Scala"? Then the runtime pulls in more and more
| responsibility until it's easier to consume a raw AST and from
| there it's not all that far to making types optional.
| speed_spread wrote:
| Garbage collection is actually faster than generic malloc for
| allocating memory because it can work as a simple bump
| allocator. And there are ways to handle collection
| efficiently. Malloc is also not entirely deterministic in
| performance because the heap can get fragmented. Either way,
| if latency matters you end up having to care about
| (de)allocation patterns at the app level.
| nu11ptr wrote:
| Agreed, it seems weird to me to avoid garbage collection in
| a high level language. It is one thing to use escape
| analysis to avoid creating garbage, but mallocing every
| object is going be slower than a well tuned GC.
| couchand wrote:
| > mallocing every object
|
| So don't do that then? Put most things on the stack. It's
| far faster than any allocation.
| kaba0 wrote:
| That's also true of a GCd language though.
| nu11ptr wrote:
| In the context of escape analysis (which would place many
| objects on the stack) that should have read: mallocing
| every _heap_ object
| estebank wrote:
| I would say that in practice 80% of the values go on the
| stack, 18% in Box and 2% in an Arc/Rc. That's why Rust
| code tends to be fast: the common cases are really easy
| to represent with the borrow checker, so a hypothetical
| GC doesn't have to perform escape analysis to see if it
| is ok to specialise those allocations, while the more
| uncommon cases can still be represented, albeit more
| verbosely than a GCd language would need.
| couchand wrote:
| I think most people's concern with GC is not the allocation
| side of it? And in any case alloca blows them all out of
| the water.
|
| > if latency matters you end up having to care about
| (de)allocation patterns at the app level.
|
| Yes, and you want tools that allow you to precisely
| describe your needs, which might be more difficult if a
| lumbering brute is standing between you and your data.
| hgs3 wrote:
| Most GC concerns surround "stop the world" tracing
| collectors that "pause" the program unpredictably for an
| indeterminate time. These collectors are bad for real-
| time and soft real-time applications for obvious reasons.
| They would do better with a reference counting collector
| because its GC bookkeeping is smeared predictably across
| the run of the program.
|
| Most languages don't use reference counting because most
| applications are either one-shot console apps, GUI apps,
| or web apps - the latter two operate on "bursts" of
| input. If your app operates in "bursts" then a tracing GC
| is superior since you can delay collection until the app
| is waiting for more input. Real-time apps don't have a
| moment where they "wait" therefore they should prefer
| reference counting for its predictable performance.
|
| You have to use the right GC algorithm for the right job,
| but unfortunately programming language runtimes don't
| usually offer a choice.
| jgilias wrote:
| > but one that was meant to feel more like Java or JavaScript
|
| Those are two very different feelings though!
| pas wrote:
| compared to Scala and TS they are the same 'ewww' :S
| bananapub wrote:
| what does "creators of rust" mean? Graydon? niko? pcwalton?
| fbn79 wrote:
| niko judging from Github commits https://github.com/dada-
| lang/dada/graphs/contributors
| bananapub wrote:
| ah, thank you! I couldn't find anything on the website
| itself, should have thought to look at the code.
| lifthrasiir wrote:
| It is indicated in the last paragraph of the FAQ:
| https://dada-lang.org/docs/about/faq (It is indeed hard to
| find though!)
| peterhull90 wrote:
| Also Brian Anderson (brson) was/is a significant rust
| contributor
| yamrzou wrote:
| Their Hello, Dada! example:
|
| print("...").await
|
| I'm coming from Python, and I can't help but ask: If my goal as a
| programmer is to simply print to the console, why should I care
| about the await? This already starts with a non zero complexity
| and some cognitive load, like the `public static void main` from
| Java.
| baq wrote:
| I'd say you want something like 'debug_msg()' for this.
|
| 'print()' should be async because it does IO. In the real world
| most likely you'd see the output once you yield.
| DinaCoder99 wrote:
| Huh, typically print _is_ the debug message function vs
| explicitly writing to stdout
| dartos wrote:
| I don't think so.
|
| Normally print isn't a debug message function, people just
| use it like that. (it normally works on non debug builds)
| couchand wrote:
| Printing directly to the console, even in a console app,
| is for debug purposes only.
|
| If your console app is writing output to any device, it
| must, for instance, handle errors gracefully.
|
| That means, at least in Rust, write! rather than print!.
| lkirkwood wrote:
| What makes you say that? I almost always use println!
| over write!.
|
| From the docs: "Use println! only for the primary output
| of your program. Use eprintln! instead to print error and
| progress messages."
| couchand wrote:
| What makes me say that a well-built program properly
| handles errors?
| myrmidon wrote:
| Panic is a perfectly proper way for a well-built program
| to stop execution.
|
| There is no point in juggling around Result types if a
| failure means that you can not recover/continue
| execution. That is in fact exactly what panic! is
| intended for [1].
|
| [1]: https://doc.rust-lang.org/book/ch09-03-to-panic-or-
| not-to-pa...
| couchand wrote:
| Panic is perfectly fine in certain cases, but it's
| absolutely not a general error-handling mechanism for
| Good Programs (TM). (Some contexts excluded, horses for
| courses and all that)
|
| You can and should recover from bog standard IO failures
| in production code, and in any case you'd better not be
| panicking in library code without making it really clear
| that it's justified in the docs.
|
| If your app crashes in flames on predictable issues it's
| not a good sign that it handles the unpredictable ones
| very well.
| int_19h wrote:
| A failure to write to stdout should not be unexpected
| given that stdout is routinely redirected to files or to
| pipes, both of which can be suddenly closed or otherwise
| fail from the other direction. Yes, you can't recover in
| this case, but you should at least properly report the
| error to stderr before exiting, in a way that lets the
| _end user_ (rather than app dev) properly diagnose the
| error.
|
| Now if you fail to write to stderr, yeah, that's a good
| reason for a console app to panic. The onus is on the
| user to provide something that is "good enough" in that
| case.
|
| IMO the real problem is that print() etc defaults to
| stdout historically, but is used mostly for diagnostic
| information rather than actual output in practice, so it
| should really go to stderr instead. This would also take
| care of various issues with buffering etc.
| nine_k wrote:
| Production builds should retain all debug prints, only
| hide them behind a flag. This helps you preserve sanity
| when troubleshooting something.
| jeroenhd wrote:
| Print is a debug function in some languages, but it's
| usually just stdout. You can add all kinds of logging
| libraries that wrap around print() with prefixes and
| control sequences to add colours, but I generally don't
| bother with those myself. In those circumstances, I would
| use something like logger.debug() instead of plain print(),
| though.
|
| I personally find myself using print debugging as a last
| resort when the debugger doesn't suffice.
| wongarsu wrote:
| In rust, the common debug message function would be
| log::info! or log::debug!, with two lines of setup to make
| logs print to stderr. Or for something more ad-hock,
| there's dbg! (which adds context what you are printing, and
| doesn't care about your logging config). Not that people
| don't use print for the purpose, but it's basically never
| the best choice. I assume Dada is conceived with the same
| mindset.
| DinaCoder99 wrote:
| I disagree--println! is far more common for every day
| printf debugging than the log crate is. Do i have any
| evidence of this? No, but it takes less to type and is
| harder to mess up with log levels while working just as
| effectively.
| est wrote:
| gevent handles async fine without the explicit async/await
|
| .NET core will introduce something similar
| nine_k wrote:
| The cost of it is that when you need to make something
| explicitly async, you have to wrap it into a greenlet in a
| much more involved way.
|
| JavaScript lets you do it much more ergonomically.
| gpderetta wrote:
| Doesn't seem very involved; for example (cilk inspired
| syntax): let f = spawn { print() } //
| fork ... wait f // join. f is a linear
| type
|
| You only pay the complexity cost if you need it.
| yamrzou wrote:
| "The most effective debugging tool is still careful thought,
| coupled with judiciously placed print statements." -- Brian
| Kernighan, co-creator of Unix
| MatthiasPortzel wrote:
| > 'print()' should be async because it does IO
|
| What if I want to do synchronous IO?
| n2d4 wrote:
| Just from glancing over the docs, that doesn't seem
| supported:
|
| _> Dada, like JavaScript, is based exclusively on async-
| await. This means that operations that perform I /O, like
| print, don't execute immediately. Instead, they return a
| thunk, which is basically "code waiting to run" (but not
| running yet). The thunk doesn't execute until you await it
| by using the .await operation._
|
| Good riddance, IMO -- never been a fan of blocking IO. Dada
| does have threads though, so I wonder how that works out.
| (Forcing async/await makes a lot more sense in JavaScript
| because it's single-threaded.)
| dahart wrote:
| Then use .await?
| bastawhiz wrote:
| Node lets you cheat with "synchronous" APIs: it stops the
| whole event loop. If you start making exceptions for
| "little" bits of IO like printing to the console or reading
| files, the async parts of your code are "async when someone
| hasn't done something synchronous". Doing a `readFileSync`
| even on a small file in a hot code path means you're
| meaningfully tanking the performance of your code.
|
| What you're asking for is "stop running my code until I've
| finished printing to the console". That's what the `.await`
| does. Synchronous IO on `print()` would mean _everything in
| the whole application that logs_ suddenly blocks the whole
| application from doing _anything_ while the console is
| being written to, not just the currently running code.
|
| If you want synchronous stop-the-world IO (like Python,
| where async/await is bolted on), you shouldn't choose a
| language based around async/await concurrency.
| Alifatisk wrote:
| The reasoning with await is valid, it's an I/O call, but the
| await should maybe be hidden inside the print then?
| yamrzou wrote:
| It's a leaky abstraction
| (https://www.joelonsoftware.com/2002/11/11/the-law-of-
| leaky-a...), but maybe there is no helping it and for some
| reason it is a necessary tradeoff for performance?
| mtsr wrote:
| Maybe it's actually a non-leaky abstraction because it
| makes the async-nature explicit. The alternative is hiding
| it, but it's still going to affect your code, making that
| effectively a leaky abstraction.
| luke-stanley wrote:
| Maybe there could be something like a aprint() wrapper,
| if the authors wanted to make the async nature explicit?
| Or something else, probably not this for one of the most
| common things a programmer must do.
| steveklabnik wrote:
| Why is aprint "non leaky" but print.await "leaky"?
| luke-stanley wrote:
| Hey Steve, I wouldn't say that "print.await" is a leak
| abstraction. I think "print.await" is explicit and that's
| good, it communicates it's abstraction fairly clearly,
| presumably following a pattern used commonly in this,
| imagined language.
|
| I suppose that a wrapper like "aprint" (a convenience
| function labelled async, like with an "a" prefix), would
| be a bit better than having people continually try using
| print, not await it, and not getting the expected output
| in stdout (or whatever stream it's sent to), while they
| are in the middle of trying to test something or
| otherwise get something working because I'm of the
| opinion that common things should be easy. Maybe "people
| would generally expect a print function to just work and
| not return a promise or something" is an abstraction?
| "aprint" might actually be the wrong name I'm not sure
| I've really thought about it right.
| steveklabnik wrote:
| I agree with you personally on print.await; maybe I
| replied to the wrong person on this thread, ha!.
| gpderetta wrote:
| Why is I/O so special that need to be explicitly marked
| across the call stack? What about memory allocation, that
| can arbitrarily delay a process? Should allocating
| functions be transitively annotated? What about functions
| that lock a mutex or wait on some synchronisation
| primitive? What about those that signal a synchronization
| primitive? What about floating points, that can raise
| exceptions? What about panicking functions?
|
| Either all side effects should be marked or none should.
| Ret-connecting await annotations as an useful feature
| instead of a necessary evil is baffling.
| avianlyric wrote:
| I/O tends to be the slowest operations your software can
| perform, and also the riskiest, because you're dependent
| on so many different underlying components working
| correctly. Everything from the kernel syscall, to the
| device driver, the device itself, and potentially devices
| attached to device that's attached to your computer. In
| short IO operations are a complete shit show of possible
| problems, that can all occur while your software is
| suspended in a syscall.
|
| Memory allocation by comparison are extremely quick, and
| generally very reliable. Your system's memory subsystem
| isn't a smorgasbord of different memory drivers and
| controllers. It one memory system, taking to one memory
| controller, via an API that been standardised for
| decades, and where every implementation of that API is
| basically tested to the extreme every time a computer
| turns on. That's assuming your language even bother
| asking the OS for memory on every allocation, which it
| probably doesn't. Most language runtimes request large
| blocks of memory from the OS, then allocate out of those
| block on demand. So most "allocating functions" never
| result in syscall at all.
| gpderetta wrote:
| Memory allocation can literally fail for reasons
| completely outside the control of the application (for
| example because the OS enforces a maximum virtual memory
| size on the application).
|
| The fact the most allocations are fulfilled via internal
| pools is immaterial, at some point the allocator needs to
| ask the OS for more memory. This parallels the way that
| most I/O doesn't actually performs syscalls because of
| buffering.
|
| Also allocations might end up performing arbitrary I/O
| indirectly if the OS needs to flush dirty pages to disk
| to free up memory.
| klabb3 wrote:
| To be precise: the contract depends on the implementation.
| Here's an example:
|
| I write an in memory kv cache. It's in memory so no async
| needed. Now I create a trait and implement a second version
| with file backing. Now the children are crying because
| async needs to be retroactively added and also why, makes
| no sense etc.
| naasking wrote:
| It does make sense if you want other types of resources,
| like time and memory, to also be part of the contract.
| Async annotations let you do this but hiding the
| asynchrony does not.
| klabb3 wrote:
| Make sense might be an overstatement but ok. Then why do
| functions with sync syscalls (ie file, timers or mutex
| ops) not expose the same contractual differences? They're
| just regular functions in most languages including Rust.
|
| Perhaps anything involving syscalls should be exposed and
| contractual. I doubt it, but maybe it's important for
| some obscure ownership-of-resources reason. But then why
| the inconsistency between traditional and pooled
| syscalls? The only difference is whether the runtime sits
| in the kernel or in user space. The only one who should
| care is the runtime folks.
|
| My take has been for years that this is throwing
| complexity over the fence and shaming users for not
| getting it. And even when they do get it, they Arc<Mutex>
| everything anyways in which case you are throwing the
| baby out with the bathwater (RAII, single ownership,
| static borrowing).
| naasking wrote:
| > Then why do functions with sync syscalls (ie file,
| timers or mutex ops) not expose the same contractual
| differences? They're just regular functions in most
| languages including Rust.
|
| Because the kernel doesn't expose that contract, so they
| don't have that behaviour.
|
| > The only difference is whether the runtime sits in the
| kernel or in user space.
|
| In other words, what contracts you have control over and
| are allowed to provide.
|
| > My take has been for years that this is throwing
| complexity over the fence and shaming users for not
| getting it.
|
| I'm sure how we got here would seem baffling if you're
| going to just ignore the history of the C10K problem that
| led us to this point.
|
| You can of course paper over any platform-specific quirks
| and provide a uniform interface if you like, at the cost
| of some runtime overhead, but eliminating as much of this
| kind of implicit runtime overhead as possible seems like
| one of Rust's goals. Other languages, like Go, have a
| different set of goals and so can provide that uniform
| interface.
|
| It's probably also possible to have some of that uniform
| interface via a crate, if some were so inclined, but that
| doesn't mean it should be in the core which has a broader
| goal.
| klabb3 wrote:
| > I'm sure how we got here would seem baffling if you're
| going to just ignore the history of the C10K problem that
| led us to this point.
|
| I am not unaware of pooled syscalls. I worked on the
| internals of an async Rust runtime, although that should
| not matter for critiquing language features.
|
| The archeological dig into why things are the way they
| can come up with a perfectly reasonable story, yet at the
| same time lead to a suboptimal state for a given goal -
| which is where the opinion space lies - the space where
| I'm expressing my own.
|
| > but eliminating as much of this kind of implicit
| runtime overhead as possible seems like one of Rust's
| goals
|
| Yes, certainly. And this is where the perplexity
| manifests from my pov. Async is a higher level feature,
| with important contractual ecosystem-wide implications.
| My thesis is that async in rust is not a good solution to
| the higher level problems, because it interacts poorly
| with other core features of Rust, and because it
| modularizes poorly. Once you take the event loop(s) and
| lift it up into a runtime, the entire point (afaik - I
| don't see any other?) to abstract away tedious lower
| level event and buffer maintenance. If you just want
| performance and total control, it's already right there
| with the much simpler event loop primitives.
|
| In short, I fail to see how arguments for async can stand
| on performance merits alone. Some people disagree about
| the ergonomics issues, which I am always happy to argue
| in good faith.
| gpderetta wrote:
| >>[mutexes] are just regular functions in most languages
| including Rust.
|
| >Because the kernel doesn't expose that contract, so they
| don't have that behaviour
|
| Which OS are we talking about? Linux doesn't really have
| mutices as primitives. You can build async mutexes on top
| of eventfd and soon even on top of futexes with io_uring.
| withinboredom wrote:
| It MIGHT or might NOT be valid, it depends. In a lot of
| cases, I might just want to print, but not yield "right
| here," but later (if at all in the current method). Further,
| writing to i/o is usually non-blocking (assuming the buffers
| are big enough for whatever you are writing), so in this
| case, the await literally makes no sense.
| couchand wrote:
| The canonical reason a language adds a utility like print
| over just offering the services of the underlying console
| is to make the Hello, World example as terse as possible.
|
| IO is inherently extremely complicated, but we always want
| people to be able to do their simplified form without
| thinking about it.
| nine_k wrote:
| A smart print() implementation may check if there's enough
| output buffer, and, if so, quickly return a Future which
| has already completed. A smart scheduler can notice that
| and not switch to another green thread.
| withinboredom wrote:
| One can argue that in the VAST majority of instances,
| you'll never ever be printing so much that you'll fill
| the buffer. If you need that kind of control, just get a
| direct stream to stdout, otherwise make print() block if
| it needs to.
| avianlyric wrote:
| You might not fill the buffer. But your program might
| crash before the buffer is flushed. In that case having
| prints explicitly block until the IO is completed is very
| valuable, especially when debugging. Nobody wants to
| waste time debugging their debug code.
| secondcoming wrote:
| Surely `public static void main` has less congnitive load than
| if __name__ == "__main__": main()
| abdusco wrote:
| You don't have to do this, though. You can have an
| entrypoint.py that simply calls `main()` without that if. You
| don't even need to have modules if you want to, so you can
| write your functions and call them right after.
| wredue wrote:
| So in python, you need to understand not 1, but at least 3
| different versions of "an entry point", and to you, this is
| "less cognitive load"?
|
| I had the same issue with Swift. There's 30 ways to write
| the exact same line of code, all created by various levels
| of syntax sugar. Very annoying to read, and even more
| annoying because engaging different levels of sugar can
| engage different rulesets.
| elevatedastalt wrote:
| You don't "need" any of the entry points when you are
| beginning Python.
|
| print("Hello World") is a perfectly valid and runnable
| Python code.
|
| And when you are working on a small part of a large code
| base, you usually don't care about __main__ either. So
| yes, it's complexity but it's complexity that you don't
| need to encounter right away.
|
| Python is intuitive off the bat. public static void
| main(String[] args) is not.
| int_19h wrote:
| Interestingly, C# (which began its life as a sort of
| Java/Delphi crossover syntactically) agrees. It used to
| be that you had to write: class Program
| { static void Main() {
| Console.WriteLine("..."); } }
|
| But these days, we can just do:
| Console.WriteLine("...");
| mike_ivanov wrote:
| It should have been implemented as `def __main__(): ...`
| wtetzner wrote:
| > If my goal as a programmer is to simply print to the console,
| why should I add care about the await?
|
| Because that isn't ever anyone's actual goal? Optimizing a
| language design for "Hello World" doesn't seem like a
| particularly useful decision.
| pas wrote:
| sure, but it seems useful to be able to opt-in/opt-out of
| async easily. ie.
|
| if I want a short/simple program it would be cool to put a
| stanza on the top of the file to auto-await all futures.
| MatthiasPortzel wrote:
| It's not an end goal, maybe, but if I'm writing a complex
| program and I want to print to the console for logging or
| debugging or status, I shouldn't have to think about the
| design of that print-call. I would like to be able to focus
| on the main complexity of the program, rather than worry
| about boiler-plate complexity every time I want to print.
| avianlyric wrote:
| You seem to be making the assumption that in other
| languages calling print is a blocking function that
| guarantees the printing of a string. Which it isn't.
|
| In python print adds your string to the stdout buffer,
| which eventually gets written out to the console. But it
| not guaranteed, if you want that guarantee you need to call
| flush on the stdout IO handler.
|
| Dada has taken the approach of making blocking IO
| operations explicit, rather than purely implicit. The
| result is that if you want to perform an IO operation, you
| need to explicitly say when you want to block, rather than
| allowing an elaborate stack of runtime buffers dictate what
| happens immediately, what happens later, and what going to
| block further code execution.
|
| In short this completely exists in other languages like
| Python, you've simply not be aware of it, or aware of the
| nuanced was in which it fails. But if your someone whose
| wasted hours wrestling with Python IO system, then you'll
| appreciate the explicit nature of Dada's IO system.
| gpderetta wrote:
| Would waiting on a mutex or signaling a semaphore require
| explicit awaiting in Dada? What about faulting in an
| mmaped memory buffer?
| int_19h wrote:
| It's trivial to tell Python to block on all stdout
| writes, though. You don't have to do it on every call.
| sanderjd wrote:
| Also it immediately makes me wonder what `await` is... Is it a
| reference to a field of whatever the `print()` method is
| returning? Is it calling a method? If it's a method call
| without parentheses, how do I get a reference to a method
| without calling it?
|
| (These kinds of questions are just unavoidable though; everyone
| will have these little pet things that they subjectively prefer
| or dislike.)
| n2d4 wrote:
| They borrowed it from Rust: `.await` is special syntax,
| roughly equivalent to `await print(...)` in other languages.
|
| https://rust-lang.github.io/async-
| book/01_getting_started/04...
| sanderjd wrote:
| Yeah but for a new language I haven't seen before, I
| immediately wonder!
| spankalee wrote:
| I wonder why not do `await print()` though? It reads more
| naturally as "wait for this" and is more clearly not a
| property access.
| tubthumper8 wrote:
| Some more details on `await` as a postfix operator rather
| than prefix
|
| https://blog.ceejbot.com/posts/postfix-await/
| int_19h wrote:
| Postfix operators are much more readable when chaining or
| composing. I used to write a lot of async C#, and it
| quickly gets tiresome to constantly have to write stuff
| like (await (await (...) ...), and reading such code
| requires jumping back and forth to unravel.
|
| Amusingly, this is history repeating itself. These days
| we consider the X.Y syntax for object members quite
| natural, but historically if you look at the earliest
| examples, it was actually prefix. The first ALGOL-60
| dialects to add records used functional notation, so you
| had to do Y(X). In ALGOL-68, they made it an operator
| instead (which allowed for proper namespacing), but it
| was still prefix: Y OF X; very straightforward and
| natural. But then people pretty quickly found out that (Y
| OF (X OF (...)) does not make for readable code in
| practice.
|
| What I think they did wrong was require a period there -
| _that_ is the part that makes it look like a property
| access. It would have been better as `print() await`,
| making it clear that it is just a postfix operator.
| jlouis wrote:
| It is a fundamental question in your language design. Some
| languages make side-effects explicit one way or the other.
| Other languages handles side-effects in a more implicit
| fashion. There's a tradeoff to be made here.
| pmontra wrote:
| I'm coming from several languages (C, Perl, Java, JavaScript,
| Ruby, Python) and I strongly dislike the async/await thing.
|
| At least let people change the default. For example
| await { // all the code here // runs
| synchronously async { // except this part
| where // async methods will return early
| print("but not me!").await() } }
|
| However the remark I make to people advocating for static typed
| Ruby holds for this language too: there are already languages
| like that (in this case await by default,) we can use them and
| let Dada do its own thing.
| wredue wrote:
| Just going to be honest here:
|
| "Zero complexity print to the screen"
|
| Is, quite possibly, the dumbest argument people make in favour
| of one language over another.
|
| For experienced people, a cursory glance at the definitions
| should be enough. For new programmers, ignoring that part "for
| now" is perfectly fine. So to is "most programming languages,
| even low level ones, have a runtime that you need to provide an
| entry point to your program. In Java, that is public static
| void main. We will go over the individual aspect of this later.
| ". This really is not that difficult, even for beginners.
|
| Personally, I find more "cognitive load" in there not being an
| explicit entry point. I find learning things difficult when
| you're just telling me extremely high level *isms.
| lamontcg wrote:
| This does surface the fact that its another await/async
| red/green function language though.
|
| If they're already making it gradually typed and not low-
| level, I don't understand why they don't throw away the C
| ABI-ness of it and make it more like Ruby with
| fibers/coroutines that don't need async/await.
|
| I'd like parametric polymorphism and dynamic dispatch and
| more reflection as well if we're going to be making a non-
| low-level rust that doesn't have to be as fast as humanly
| possible.
|
| (And honestly I'd probably like to keep it statically typed
| with those escape hatches given first-class citizen status
| instead of the bolted on hacks they often wind up being)
|
| [Ed: also rather than go back to object oriented, I'd rather
| see really easy composition, delegation and dependency
| injection without boilerplate code and with strongly typed
| interfaces]
| raverbashing wrote:
| Yeah I'm not so sold, but mainly, I don't understand the logic
| here
|
| If I'm declaring an async function, why do I need to await
| inside it?
|
| like, if the return of an async function is a promise (called a
| thunk), why can't I do
|
| async async_foo() { return other_async_foo(); } and it will
| just pass the promise?
|
| Then you await on the final async promise. Makes sense?
| spankalee wrote:
| The other problem I see here is that starting and awaiting the
| task are too coupled.
|
| In JavaScript calling the function would start the task, and
| awaiting the result would wait for it. This lets you do several
| things concurrently.
|
| How would you do this in Dada: const doThings
| = async () => { const [one, two, three] = await
| Promise.all([ doThingOne(),
| doThingTwo(), doThingThree(), ]);
| };
|
| And if you wanted to return a thunk to delay starting the work,
| you would just do that yourself.
| janderland wrote:
| I assumed dada is using promises under the hood, just as JS
| is. If this is the case it could provide a static method for
| waiting on multiple promises, just as JS does.
| spankalee wrote:
| This seems to say otherwise (specifically the "but not
| running" part):
|
| Dada, like JavaScript, is based exclusively on async-await.
| This means that operations that perform I/O, like print,
| don't execute immediately. Instead, they return a thunk,
| which is basically "code waiting to run" (but not running
| yet). The thunk doesn't execute until you await it by using
| the .await operation.
|
| From https://dada-lang.org/docs/dyn_tutorial
| pama wrote:
| In Python if you carelessly print within a multiprocess part of
| an application you may end up getting a nonreproducible mess on
| stdout with multiple streams merged at random points. So the
| cognitive load in this example is that this new language is
| meant for multithreaded coding and can make multithreading easy
| compared to other languages.
| bmitc wrote:
| That's a great example of the "simplicity" of Python being
| anything but.
| int_19h wrote:
| This is not at all unique to Python, and a footgun present
| in any language that allows multiple threads.
|
| But if you're spawning multiple threads - in Python or any
| other language - you're already past any semblance of
| "simplicity", threads or no threads.
| Rucadi wrote:
| no upfront types, for me this is unusable sadly
| fweimer wrote:
| Gradual lifetimes could be interesting, though.
| leiroigh wrote:
| ^this!
|
| In garbage-collected languages, please give me gradual /
| optional annotations that permit deterministic fast freeing
| of temps, in code that opts in.
|
| Basically to relieve GC pressure, at some modest cost of
| programmer productivity.
|
| This unfortunately makes no sense for small bump-allocated
| objects in languages with relocating GC, say typical java
| objects. But it would make a lot of sense even in the JVM for
| safe eager deterministic release of my 50mb giant buffers.
|
| Another gradual lifetime example is
| https://cuda.juliagpu.org/stable/usage/memory/ -- GPU
| allocations are managed and garbage collected, but you can
| optionally `unsafe_free!` the most important ones, in order
| to reduce GC pressure (at significant safety cost, though!).
| diggan wrote:
| Literally every single program you ever created has needed
| types?
|
| I've probably written 100s of tiny little utility programs that
| are a couple of lines at most, and wouldn't need types for any
| of those, it would just add extra verbosity for no gain.
| Alifatisk wrote:
| Why the name and the logo? Couldn't find info about it.
|
| Otherwise, the idea of creating something close to rust but
| without the complexity sounds interesting. I just hope they don't
| stick to that name.
| yawpitch wrote:
| They're both referencing the Dada artistic movement.
| Alifatisk wrote:
| Thx
| w-m wrote:
| I was thoroughly confused reading the Dada Manifesto[0],
| starting with the non-existent German meanings of the word dada
| and getting much stranger from there. Until I found out at the
| very bottom that it's a riff on a 1916 dada manifesto.
|
| [0]: https://dada-lang.org/blog/manifesto
| Schattenbaer wrote:
| Logo might be inspired by Marcel Duchamp's _Bicycle Wheel_
|
| see https://www.moma.org/collection/works/81631
| brakmic wrote:
| Dada: https://en.wikipedia.org/wiki/Dada
| bsimpson wrote:
| Very cool art movement: it's essentially a prototypical form of
| Photoshop/meme culture as protest against the Nazis. John
| Heartfield is my favorite Dada artist.
|
| Perhaps his most famous piece is a photo of Hitler captioned
| "millions stand behind me," showing a donor passing him stacks
| of cash.
| VMG wrote:
| the contrast of the links against the light background is pretty
| poor
| anentropic wrote:
| don't know why you were down voted - this is totally correct,
| the site only looks right in dark mode
| happens wrote:
| It's weird, I want pretty much the exact opposite of this: a
| language with the expressive type system and syntax of rust, but
| with a garbage collector and a runtime at the cost performance.
| Basically go, but with rusts type system.
|
| I'm aware that there are a few languages that come close to this
| (crystal iirc), but in the end it's adoption and the ecosystem
| that keeps me from using them.
| GardenLetter27 wrote:
| Yeah, same for a scripting language too - something like Lua
| but as expressive as Rust.
|
| There is Rune, but like you mentioned the issue is adoption,
| etc.
| thegeekpirate wrote:
| Right? One day... _sigh_
| quadrature wrote:
| You've just described scala.
| sanderjd wrote:
| Ha, no. Scala does contain this language the parent
| described, but alongside the huge multitudes of other
| languages it also contains.
| kaba0 wrote:
| Scala is an absolutely small language. It is just very
| expressive, but its complexity is quite different than,
| say, Cpp's, which has many features.
| sanderjd wrote:
| In my view you have compared it to the only other
| language for which it is small by comparison :) But
| different strokes for different folks! I have nothing
| against Scala, its multi-paradigm thing is cool and
| impressive, it just isn't for me except by way of
| curiosity.
| kaba0 wrote:
| Could you list all the features you are thinking of?
| dartos wrote:
| That sounds... bad?
|
| The whole point of rusts type system is to try to ensure safe
| memory usage.
|
| Opinions are opinions, but if I'm letting my runtime handle
| memory for me, I'd want a lighter weight, more expressive type
| system.
| umanwizard wrote:
| I'm assuming by rust's type system they mean without
| lifetimes. In which case it's existed in lots of GC languages
| (OCaml, Haskell) but no mainstream ones. It isn't really
| related to needing a GC or not.
| gpderetta wrote:
| You still want RAII and unique references, but rely on GC
| for anything shared, as if you had a builtin refererence
| counted pointer.
|
| I do also believe this might be a sweet spot for a
| language, but the details might be hard to reconcile.
| umanwizard wrote:
| I haven't used Swift so I might be totally wrong but
| doesn't it work sort of like you describe? Though perhaps
| with ARC instead of true GC, if it followed in the
| footsteps of Objective-C.
| gpderetta wrote:
| Possibly, yes. I haven't used swift either though. Does
| it have linear/affine types?
|
| Edit: I would also prefer shared nothing parallelism by
| default so the GC can stay purely single threaded.
| dartos wrote:
| Without lifetimes, Pins, Boxes, Clone, Copy, and Rc (Rc as
| part of the type itself, at least)
| afavour wrote:
| I like Rust's type system just fine but for me it's types
| combined with language features like matching that draw me to
| Rust. When I was still learning I made an entire project
| using Arc<> with no lifetimes at all and it was actually a
| great experience, even if it's not the textbook way to use
| Rust.
| sanderjd wrote:
| Honestly, I think syntax for Arc (and/or Rc or some
| generalization of the two) and more "cultural" support for
| writing in that style would have benefitted rust back when
| 1.0 was being finalized. But I think the cow is out of the
| barn now on what rust "is" and that it isn't this.
| cmrdporcupine wrote:
| Yes, if you think about it, it's a bit weird that async
| gets first syntactical class treatment in the language
| but reference counting does not. A similar approach of
| adding a syntactical form but not mandating a particular
| impl could have been taken, I think.
|
| Same for Box, but in fact Rust went the opposite way and
| turfed the Box ~ sigil.
|
| Which I actually feel was a mistake, but I'm no language
| designer.
| zozbot234 wrote:
| Async has to get first-class treatment in the syntax
| because the whole point of it is a syntax-level
| transformation, turning control flow inside out. You can
| also deal with Future<> objects manually, but that's
| harder. A special syntax for boxed variables adds nothing
| over just using Box<> as part of the type, similar for
| Rc<> (note that in any language you'll have to
| disambiguate between, e.g. cloning the Rc reference
| itself vs. duplicating its contents, except that Rust
| does it without having to use special syntax).
| sanderjd wrote:
| Yeah, but personally I think Rc/Arc is more deserving of
| syntax than Box!
| steveklabnik wrote:
| A long time ago, it _did_ have specialized syntax! We
| fought to remove it. There's a variety of reasons for
| this, and maybe it would make sense in another language,
| but not Rust.
| sanderjd wrote:
| For Arc/Rc? I don't recall that! What was it? I recall it
| being `&borrowed`, `~boxed`, `@garbage_collected`.
|
| Aaaah, I'm realizing in typing this that the `@foo`
| syntax was actually implemented via reference counting? I
| think my intuition at the time was that the intention was
| for those to eventually be backed by a mark-and-sweep GC,
| which I did think was a poor fit for the rest of the
| language. But as just a syntax for reference counting, I
| honestly think it might have been an ok fit.
|
| Or maybe not, I'm ambivalent. But the syntax thing in my
| comment is more of a red herring for what I think is more
| of a cultural "issue" (to the small extent it is an issue
| at all), which is that most Rust projects and programmers
| seem to try to write in a style that defaults to only
| choose reference counting when they must, rather than
| using a style of optimizing them out if they show up in a
| hotspot during profiling.
| steveklabnik wrote:
| Yes, I'm referring to @foo, which IIRC maybe in the VERY
| old days had a GC but from when I got involved in 2012
| was reference counting, iirc.
|
| Regardless of the specifics here, the same problems
| apply. Namely that it privileges specific
| implementations, and makes allocation part of the
| language.
| iopq wrote:
| @gc references were Arc under the hood!
| wongarsu wrote:
| Rust's type system prevents bugs far beyond mere memory bugs.
| I would even go as far as claiming that the type system
| (together with the way the standard library and ecosystem use
| it) prevents at least as many logic bugs as memory bugs.
| dartos wrote:
| The type system was built to describe memory layouts of
| types to the compiler.
|
| But I don't think it prevents any more logic bugs than any
| other type system that requires all branches of match and
| switch statements to be implemented. (Like elm for example)
| speed_spread wrote:
| It prevents a lot more than that. For example, it
| prevents data race conditions through Send/Sync traits
| propagation.
| kaba0 wrote:
| Besides preventing data races (but not other kinds of race
| conditions), it is not at all unique. Haskell, OCaml,
| Scala, F# all have similarly strong type systems.
| sanderjd wrote:
| > _The whole point of rusts type system is to try to ensure
| safe memory usage._
|
| It isn't though. The whole trait system is unnecessary for
| this goal, yet it exists. ADTs are unnecessary to this goal,
| yet they exist. And many of us like those aspects of the type
| system even more than those that exist to ensure safe memory
| usage.
| dartos wrote:
| It is the first and foremost goal of every language choice
| in rust.
|
| I think traits muddy that goal, personally, but their
| usefulness outweighs the cost (Box<dyn ATrait>)
|
| I should've probably said "the whole point of rusts type
| system, other than providing types and generics to the
| language"
|
| But I thought that went without saying
| sanderjd wrote:
| > _It is the first and foremost goal of every language
| choice in rust._
|
| It ... just ... _isn 't_, though.
|
| I mean, I get what you're saying, it's certainly
| foundational, Rust would look incredibly different if it
| weren't for that goal. But it just isn't the case that it
| is "the first and foremost goal of every language choice
| in rust".
|
| I followed the language discussions in the pre-1.0 days,
| and tons of them were about making it easier and more
| ergonomic to create correct-if-it-compiles code, very
| often in ways that had zero overlap with safe memory
| usage.
|
| Traits don't "muddy that goal", they are an important
| feature of the language in and of themselves. Same thing
| with the way enums work (as arithmetic data types), along
| with using Option and Result for error handling, rather
| than exceptions. Same thing with RAII for tying the
| lifecycle of other resources to the lifecycle of values.
|
| The memory safety features _interact_ with all these
| other features, for sure, and that must be taken into
| account. But there are many features in the language that
| exist because they were believed to be useful on their
| own terms, not in subservience to safe memory usage.
|
| And it's not just about "providing types and generics to
| the language", it's a whole suite of functionality
| targeted at static correctness and ergonomics. The
| ownership/lifetime/borrowing system is only one
| (important!) capability within that suite.
| BWStearns wrote:
| The whole reason I got interested in Rust in the first place
| was because of the type system. I viewed it as "Haskell types
| but with broad(er) adoption". The fact that it also has this
| neat non-GC but memory safe aspect was cool and all but not
| the main sell for me.
| cmrdporcupine wrote:
| ... so OCaml or StandardML then
| bradrn wrote:
| Or Haskell!
| aloisdg wrote:
| or F#
| sanderjd wrote:
| Ocaml, yes, but not haskell. It does include these things
| the parent wants, but similar to how Rust ends up being
| quite "captured" by its memory semantics and the mechanics
| necessary to make them work, haskell is "captured" by
| laziness and purity and the mechanics necessary to make
| those work.
|
| Also, syntax does actually matter, because it's the first
| thing people see, and many people are immediately turned
| off by unfamiliarity. Rust's choice to largely "look like"
| c++/java/go was a good one, for this reason.
| cmrdporcupine wrote:
| I learned SML/NJ and OCaml a bit over 20 years ago and
| liked them, but when I tried my hand at Haskell my eyes
| glossed over. I get its power. But I do not like its
| syntax, it's hard to read. And yes, the obsession with
| purity.
| sanderjd wrote:
| Exactly right. I quite like haskell in theory, but in
| practice I quite dislike both reading and writing it.
|
| But I like ocaml both in theory and practice (also in
| part due to having my eyes opened to SML about 20 years
| ago).
| cmrdporcupine wrote:
| I actually preferred SML/NJ when I played with writing
| it, but OCaml "won" in the popularity contest. Some of
| the things that made OCaml "better" (objects, etc.)
| haven't aged well, either.
|
| Still with OCaml finally supporting multicore and still
| getting active interest, I often ponder going back and
| starting a project in it someday. I really like what I
| see with MirageOS.
|
| These days I just work in Rust and it's Ok.
| sanderjd wrote:
| Yep, right there with you. OCaml was only ever better in
| my view because it had developed enough libraries to be
| an actual pragmatic choice, unlike the other languages in
| that family. And yep, Rust is perfectly good too, IMO,
| but I do find that I rarely-to-never actually care about
| all the zero-cost abstractions that make it "hard" to
| use.
| int_19h wrote:
| OCaml's object system is very nice, though. Structural
| typing with full inference is pretty awesome, and it also
| cleanly decouples subtyping from implementation
| inheritance.
| malermeister wrote:
| You might like Kotlin. It'll also give you access to the entire
| JVM ecosystem.
| helsinki wrote:
| Is that a blessing or a curse?
| mike_hearn wrote:
| A blessing. Do you really want to write all the libraries
| from scratch for a new language? Do you want to come up
| with portable abstractions that work well on Windows? (and
| don't think you can skip that, people will ask).
|
| Most people don't. That's not the fun part of language
| design.
| iainmerrick wrote:
| TypeScript maybe?
| actionfromafar wrote:
| If we are going that far, I suggest hopping off just one
| station earlier at Crystal-lang.
| sanderjd wrote:
| Yep, I think Crystal is the thing that is making a real go
| at essentially this suggestion. And I think it's a great
| language and hope it will grow.
| iainmerrick wrote:
| Do you know how Crystal compares with Haxe? That's
| another one that might fit the requirements nicely.
| actionfromafar wrote:
| I don't understand the Haxe documentation but it seems to
| also have some kind of algebraic data type.
| k__ wrote:
| Maybe ReScript?
| overstay8930 wrote:
| You have awoken the ocaml gang
| galangalalgol wrote:
| That is probably the closest, especially if they add
| ownership. That was the rust inventor's original goal, not
| just safety at minimal performance cost. I think ownership
| should be a minimal requirement for any future language, and
| we should bolt it on to any that we can. Fine grained
| permissions for dependency trees as well. I like static types
| mostly because they let me code faster, not for correctness,
| strong types certainly help with that though. Jit makes
| static types have some of the same ergonomic problems as
| dynamic ones though. I think some sort of AGI enslaved to do
| type inference and annotate my code might be ok, and maybe it
| could solve ffi for complex types over the c abi while it is
| at it.
| color_me_not wrote:
| There's no ownership concept, but in the JaneStreet fork,
| there is something resembling lifetimes[1].
|
| [1]: https://blog.janestreet.com/oxidizing-ocaml-locality/
| sanderjd wrote:
| Yeah, ocaml is awesome! Frankly, if it had a more familiar
| syntax but the same semantics, I think its popularity would
| have exploded in the last 15 years. It's silly, but syntax is
| the first thing people see, and it is only human to form
| judgments during those moments of first contact.
| zozbot234 wrote:
| > Frankly, if it had a more familiar syntax but the same
| semantics
|
| That's what ReasonML is? Not quite "exploding" in
| popularity, but perhaps more popular than Ocaml itself.
| ericjmorey wrote:
| Don't forget ReScript
| sanderjd wrote:
| Interesting! I'm actually unaware of this, but will look
| into it.
| bmitc wrote:
| F# has better syntax but is ignored. :(
| anentropic wrote:
| Funny, because the semicolons and braces syntax is one of
| the things that puts me off Rust a bit, and I was not
| excited to see it in Dada
| estebank wrote:
| Syntax in programming languages are a question of style
| and personal preference. At the end of the day syntax is
| meant to help programmers communicate intent to the
| compiler. More minimalist syntax trades off less typing
| and reading for less redundancy and specificity. More
| verbose and even redundant syntax is in my opinion
| _better_ for languages, because it gives the compiler and
| humans "flag posts" marking the intent of what was
| written. For humans, that can be a problem because when
| there are two things that need to be written for a
| specific behavior, they will tend to forget the other,
| but for compilers that's great because it gives them a
| lot of contextual information for recovery and more
| properly explaining to the user what the problem was.
| Rust could have optional semicolons. If you go and remove
| random ones in a file the compiler will tell you exactly
| where to put them back. 90% of the time, when it isn't
| ambiguous. But in an expression oriented language you
| _need_ a delimiter.
| sanderjd wrote:
| It isn't necessarily my preference either, but it's the
| most familiar style of syntax broadly, and that matters
| more for adoption than my personal preferences do.
| rpeden wrote:
| You might enjoy F#. It's a lot like OCaml (which others have
| mentioned) but being part of the .NET ecosystem there are
| libraries available for pretty much anything you might want to
| do.
| jug wrote:
| Yes, F# is an often forgotten gem in this new, brighter
| cross-platform .NET world. :)
| asplake wrote:
| :-) Is F# a contender outside the .NET world?
| posix_monad wrote:
| There aren't many languages that can do server-side and
| browser-side well. F# is one of them!
| asplake wrote:
| Non .NET server-side?
| posix_monad wrote:
| You can do Node.js with F#
|
| But these days .NET is a great server-side option. One of
| the fastest around, with a bit of tuning.
| bmitc wrote:
| What do you mean by "outside the .NET world"? F# is a
| .NET language (more specifically a CLR language). That
| question seems to be like asking "are Erlang and Elixir
| contenders outside of the BEAM world?" or "is Clojure a
| contender outside of the JVM world?".
|
| F# being on top of the CLR and .NET is a _benefit_. It is
| very easy to install .NET, and it comes with a huge
| amount of functionality.
|
| If you're asking if the language F# could be ported to
| another VM, then I'd say yes, but I don't see the point
| unless that VM offered similar and additional
| functionality.
|
| You can use F# as if C# didn't exist, if that's what you
| mean, and by treating .NET and CLR as an implementation
| detail, which they effectively are.
| neonsunset wrote:
| This conversation could be referring to https://fable.io/
|
| Other than that, the question is indeed strange and I
| agree with your statements.
| kaba0 wrote:
| You are generally right, but Clojure is a bad example, it
| is quite deliberately a "hosted" language, that can and
| does have many implementations for different platforms,
| e.g. ClojureScript.
| bmitc wrote:
| Yea, that's true. I forgot about that. I did think of
| Clojure CLR, but I don't get the impression that this is
| an all that natural or used implementation so I ignored
| it. ClojureScript is obviously much more used, although
| it is still a "different" language.
|
| https://github.com/clojure/clojure-clr
| gary17the wrote:
| If you do not want to mess with Rust borrow checker, you do not
| really need a garbage collector: you can rely on Rust reference
| counting. Use 1.) Rust reference-counted smart pointers[1] for
| shareable immutable references and 2.) Rust internal
| mutability[2] for non-shareable mutable references checked at
| runtime instead of compile time. Effectively, you will be
| writing kind of verbose Golang with Rust's expressiveness.
|
| [1] https://doc.rust-lang.org/book/ch15-04-rc.html
|
| [2] https://doc.rust-lang.org/book/ch15-05-interior-
| mutability.h...
| amw-zero wrote:
| A language has a paved road, and when you go off of that road
| you are key with extreme annoyance and friction every step of
| the way.
|
| You're telling people to just ignore the paved road of Rust,
| which is bad advice.
| dewbrite wrote:
| I strongly disagree that smart pointers are "off the paved
| road". I don't even care to make specific arguments against
| that notion, it's just a terrible take.
| gary17the wrote:
| No, not really. Firstly, there is no significant "friction"
| to using Rust smart pointers and internal mutability
| primitives, as those constructs have been added to Rust for
| a reason: to solve certain borrow checker edge cases (e.g.,
| multiply interconnected data structures), so they are
| treated by the Rust ecosystem as first-class citizens.
| Secondly, those constructs make a pretty good educational
| tool. By the time people get to know Rust well enough to
| use those constructs, they will inevitably realize that
| mastering the Rust borrow checker is just one book chapter
| away to go through out of passion or boredom.
| wredue wrote:
| I find quite a lot of friction in being demanded to
| understand all of the methods, what they do, when you'd
| use them, why you'd choose one over another that does a
| slightly different thing, but maybe still fits.
|
| The method documentation alone in reference counting is
| more pages than some entire programming languages. That's
| beside the necessary knowledge for using it.
| gary17the wrote:
| I don't think it's necessary to understand every single
| `Rc<T>` method[1] to use Rust smart pointers to learn
| Rust. Perhaps try a different learning resource such as
| "Rust By Example"[2], instead?
|
| [1] https://doc.rust-lang.org/std/rc/struct.Rc.html
|
| [2] https://doc.rust-lang.org/rust-by-example/std/rc.html
| Groxx wrote:
| It's telling people to avoid the _famously hard_ meme-road.
|
| Mutexes and reference counting work fine, and are sometimes
| _dramatically_ simpler than getting absolutely-minimal
| locks like people seem to always want to do with Rust.
| rcxdude wrote:
| Reference counting and locks often is the easy path in
| Rust. It may not feel like it because of the syntax
| overhead, but I firmly believe it should be one of the
| first solutions on the list, not a last resort. People get
| way too fixed on trying to prove to the borrow checker that
| something or another is OK, because they feel like they
| need to make things fast, but it's rare that the overhead
| is actually relevant.
| 12_throw_away wrote:
| Yes! Thank you! Dunno what it is about Rust that makes
| everyone forget what premature optimization is the root
| of all of.
| bombela wrote:
| The zero cost abstraction is so tantalizingly close
| enough to reach!
|
| I tell everybody to .clone() and (a)rc away and optimize
| later. But I often struggle to do that myself ;)
| int_19h wrote:
| If it's syntactically messy, though, it's not really the
| easy path. Ergonomics matter just as much as semantics.
|
| I do think that a superset of Rust that provided first-
| class native syntax for ARC would be much more popular.
| zozbot234 wrote:
| This is what Swift does, and it has even lower performance
| than tracing GC.
|
| (To be clear, using RC for everything is fine for prototype-
| level or purely exploratory code, but if you care about
| performance you'll absolutely want to have good support for
| non-refcounted objects, as in Rust.)
| gary17the wrote:
| An interesting point, but I would have to see some very
| serious performance benchmarks focused specifically on,
| say, RC Rust vs. GC Golang in order to entertain the notion
| that an RC PL might be slower than a GC PL. Swift isn't,
| AFAIK, a good yardstick of... anything in particular,
| really ;) J/K. Overall PL performance is not only dependent
| on its memory management, but also on the quality of its
| standard library and its larger ecosystem, etc.
| MuffinFlavored wrote:
| Can you help me understand when to use Rc<T> instead of
| Arc<T> (atomic reference counter)?
|
| Edit: Googled it. Found an answer:
|
| > The only distinction between Arc and Rc is that the former
| is very slightly more expensive, but the latter is not
| thread-safe.
| gary17the wrote:
| The distinction between `Rc<T>` and `Arc<T>` exists in the
| Rust world only to allow the Rust compiler to actually
| REFUSE to even COMPILE a program that uses a non- thread-
| safe primitive such as a non-atomic (thus susceptible to
| thread race conditions) reference-counted smart pointer
| `Rc<T>` with thread-bound API such as `thread::spawn()`.
| (Think 1-AM-copy-and-paste from single-threaded codebase
| into multi-threaded codebase that crashes or leaks memory 3
| days later.) Otherwise, `Rc<T>`[1] and `Arc<T>`[2] achieve
| the same goal. As a general rule, many Rust interfaces
| exist solely for the purpose of eliminating the possibility
| of particular mistakes; for example, `Mutex<T>` `lock()`[3]
| is an interesting one.
|
| [1] https://doc.rust-lang.org/rust-by-example/std/rc.html
|
| [2] https://doc.rust-lang.org/rust-by-example/std/arc.html
|
| [3] https://doc.rust-lang.org/std/sync/struct.Mutex.html
| BoppreH wrote:
| I've always wondered if global type inference wouldn't be a
| game changer. Maybe it could be fast enough with caching and
| careful language semantics?
|
| You could still have your IDE showing you type hints as
| documentation, but have inferred types to be more fine grained
| than humans have patience for. Track units, container
| emptiness, numeric ranges, side effects and idempotency,
| tainted values for security, maybe even estimated complexity.
|
| Then you can tap into this type system to reject bad programs
| ("can't get max element of potentially empty array") and add
| optimizations (can use brute force algorithm because n is known
| to be small).
|
| Such a language could cover more of the script-systems
| spectrum.
| bananapub wrote:
| one of the other reasons global inference isn't used is
| because it causes weird spooky action at a distance -
| changing how something is used in one place will break
| _other_ code.
| BoppreH wrote:
| I've heard that, but never seen an example*. If the type
| system complains of an issue in other code after a local
| change, doesn't that mean that the other code indeed needs
| updating (modulo false positives, which should be rarer
| with granular types).
|
| Or is this about libraries and API compatibility?
|
| * I have seen examples of spooky-action-at-a-distance where
| usage of a function changes its inferred type, but that
| goes away if functions are allowed to have union types,
| which is complicated but not impossible. See:
| https://github.com/microsoft/TypeScript/issues/15114
| nu11ptr wrote:
| Try writing a larger OCaml program and not using
| interface files. It definitely happens.
| BoppreH wrote:
| I've never used OCaml, so I'm curious to what exactly
| happens, and if language design can prevent that.
|
| If I download a random project and delete the interface
| files, will that be enough to see issues, or is it
| something that happens when writing new code?
| nu11ptr wrote:
| If you delete your interface files and then change the
| type used when calling a function it can cascade through
| your program and change the type of the function
| parameter. For this reason, I generally feel function
| level explicit types are a fair compromise. However,
| making that convention instead of required (so as to
| allow fast prototyping) is probably fine.
| iopq wrote:
| Just require it for public functions. Your own code can
| be as messy as you want unser the hood
| Narishma wrote:
| > If the type system complains of an issue in other code
| after a local change, doesn't that mean that the other
| code indeed needs updating
|
| The problem is when it doesn't complain but instead
| infers some different type that happens to match.
| mattgreenrocks wrote:
| Type inference is powerful but probably too powerful for
| module-level (e.g. global) declarations.
|
| Despite type systems being powerful enough to figure out what
| types should be via unification, I don't think asking
| programmers to write the types of module declarations is too
| much. This is one area where forcing work on the programmer
| is really useful to ensure that they are tracking boundary
| interface changes correctly.
| BoppreH wrote:
| People accept manually entering types only at a relatively
| high level. It'd be different if types were "function that
| takes a non-empty list of even numbers between 2 and 100,
| and a possibly tainted non-negative non-NaN float in
| meters/second, returning a length-4 alphanumeric string
| without side effects in O(n)".
| 63stack wrote:
| I dabbled a bit with ReasonML which has global type
| inference, and the error messages from the compiler became
| very confusing. I assume that's a big reason for not gaining
| more adoption.
| efficax wrote:
| use scala
| sanderjd wrote:
| Totally agree! But I think it's a "both and" rather than an
| "either or" situation. I can see why people are interested in
| the experiment in this article, and I think your and my
| interest in the other direction also makes sense.
| naasking wrote:
| Isn't that just the Boehm GC with regular Rust?
| bmitc wrote:
| Isn't that F#?
| mattgreenrocks wrote:
| Kotlin scratches that itch well for me. My only complaints are
| exceptions are still very much a thing to watch, and ADT
| declarations are quite verbose when compared with more pure FP
| languages.
|
| Still, the language is great. Plus, it has Java interop, JVM
| performance, and Jetbrains tooling.
| keeperofdakeys wrote:
| The funny thing is that rust used to have things like garbage
| collection. For the kind of language Rust wanted to be,
| removing them was a good change. But there could always be a
| world where it kept them.
|
| https://pcwalton.github.io/_posts/2013-06-02-removing-garbag...
| Georgelemental wrote:
| > the kind of language Rust wanted to be
|
| That has changed through the years:
| https://graydon2.dreamwidth.org/307291.html
| iopq wrote:
| The @blah references were actually just Arc sugar
| lawn wrote:
| Take a look at Gleam!
|
| For me it seems like the perfect match.
| geodel wrote:
| > but in the end it's adoption and the ecosystem that keeps me
| from using them.
|
| Well, since you can't really use without high adoption even if
| something comes up with all features you want, you still won't
| be able to use it for decades or longer.
| weatherlight wrote:
| checkout Gleam.
| posix_monad wrote:
| There are a bunch of languages that fit-the-bill already. F#,
| OCaml, Haskell and Scala all come to mind.
|
| You might have to lose a few parens though!
| pie_flavor wrote:
| The expressive type system of Rust is backed by use-site
| mutability; use-site mutability is backed by single ownership;
| single ownership is made usable by borrow checking. There's a
| reason no language before Rust has been like Rust without being
| a functional language (and if that's no object, then you can
| use OCaml).
| emporas wrote:
| The absence of GC, makes embedded Rust a joy. It can be easily
| attached to other programs like Erlang with NIFs, Javascript and
| web pages with Web Assembly and Emacs with command line
| execution. Micro-controllers as well of course.
|
| I do consider the lightning start-up speed of a program to be one
| of the killer features of Rust. Rust with garbage collection
| throws away one of it's biggest advantages compared to every
| other language around.
| zem wrote:
| don't think of it as rust with garbage collection, think of it
| as a GC language with features borrowed from rust
| mike_hearn wrote:
| Garbage collection doesn't make program startup slow. Look at
| Go, or Java compiled with native-image.
| munificent wrote:
| GC doesn't affect startup time.
|
| The slow startup you associate with GC language implementations
| like ones for Java and JavaScript mostly comes from JIT warmup.
| Doctor_Fegg wrote:
| > What if we were making a language like Rust, but one that was
| meant to feel more like Java or JavaScript, and less like C++?
|
| That would be Swift?
|
| Interesting experiment. But it does seem like there are
| increasing numbers of languages trying to crowd into the same
| spaces.
| nu11ptr wrote:
| Yes, but languages don't compose well. For example, you can't
| take Swift because you like all the things the language does
| and then add in first class support for Linux and Windows.
| Thus, anytime a language doesn't align with EVERY thing you
| need it to do... a new language evolves.
| actionfromafar wrote:
| What is Dada?
| m0llusk wrote:
| exactly
| jokethrowaway wrote:
| The main idea is that leases are an easier concept to understand
| than borrowing and lifetimes?
|
| I don't think it will be, it sounds like a concept of similar
| complexity and it won't make it an "easy language".
|
| People are scared of Typescript, so a typed language with an
| extra ownership concept will sound exactly like rust in terms of
| difficulty.
|
| Not that I get the reputation of Rust being hard, even as a
| complete novice I was able to fight a bit with the compiler and
| get things working.
|
| The gradually typed approach is nice but it just sounds like
| smarter type inference would get you 99% there while keeping the
| performance (instead of using runtime checks).
|
| Not having unsafe code is both interesting and limiting. I keep
| all my code safe for my own mental sanity but sometimes having
| bindings to some big library in c/c++ is convenient (eg Qt or
| OpenCV).
| turnsout wrote:
| Yeah, it's not clear who this is for. If you can handle
| ownership, this doesn't seem to have many benefits over Rust.
| If you can't handle ownership, and don't mind a runtime, just
| use Swift, which seems to be the main inspiration for Dada's
| syntax.
| couchand wrote:
| > As of right now, Dada doesn't really exist, though we have some
| experimental prototypes...
|
| > OK, from here on out I'm going to pretend that Dada really
| exists in its full glory.
|
| This is a brilliant trick I only recently discovered in another
| context: write the docs first, to validate the user experience of
| a novel system.
| Twirrim wrote:
| During architectural reviews, I'm often the annoying person
| grilling the team on the customer experience. If you don't
| start from how the customer will interact with it, how are you
| going to create anything ergonomic?
|
| All too often, the engineering has started at "customers want
| to be able to do $x", and that's the last time the customer was
| part of the consideration. The solutions are great, but often
| miss out on what it'd be like to actually use it, as a
| customer. Lots of foot guns, and expectations of knowledge that
| a customer couldn't possibly have unless they had as much
| understanding of what happens under the hood as the engineers
| did, etc.
| alphazard wrote:
| Just so everyone knows. Graydon is not in the list of
| contributors on GitHub.
|
| https://github.com/dada-lang/dada/graphs/contributors
|
| https://github.com/graydon
| benrutter wrote:
| I love the idea of a "thought experiment language" - actually
| creating a working language is a big overhead, and its really fun
| to think about what an ideal language might look like.
|
| The crazy thing with reading this and the comments, is that it
| seems like we all have been daydreaming about completely
| different versions of a "high level rust" and what that would
| look like. For me I'd just want a dynamic run time + simpler
| types (like "number" or a single string type), but it looks like
| other people have a completely different list.
|
| Some of the additions here, like a gradual type system, I would
| really _not_ want in a language. I love gradual type system for
| stuff like Python, Typescript and Elixir, but those are cases
| where there 's already so much untyped code written. I would way
| prefer the guarantees of a fully static typed codebase from day
| one when that's an option.
| brainzap wrote:
| I agree, fantasy and play is needed. Since we humans have a
| brain area for play and imagination, why not explore.
| thesz wrote:
| > actually creating a working language is a big overhead
|
| Languages, with first class values, pattern matching, rich
| types, type inference and even fancy RTS, often can be embedded
| in Haskell.
|
| For one example, it is very much possible to embed into Haskell
| a Rust-like language, even with borrow checking (which is type-
| checking time environment handling, much like linear logic).
| See [1], [2] and [3]. [1]
| http://blog.sigfpe.com/2009/02/beyond-monads.html [2]
| https://www.cs.tufts.edu/comp/150FP/archive/oleg-
| kiselyov/overlooked-objects.pdf [3]
| http://functorial.com/Embedding-a-Full-Linear-Lambda-Calculus-
| in-Haskell/linearlam.pdf
|
| Work in [3] can be expressed using results from [1] and [2], I
| cited [3] as an example of what proper type system can do.
|
| These results were available even before the work on Rust
| began. But, instead of embedding Rust-DSL into Haskell, authors
| of Rust preferred to _implement_ Rust in OCaml.
|
| They do the same again.
| pas wrote:
| > instead of embedding Rust-DSL into Haskell, authors of Rust
| preferred to implement Rust in OCaml
|
| why? and how much does it matter, if the goal is to have a
| compiler/interpreter? (as I assume is the case with Dada, and
| was with Rust)
| argiopetech wrote:
| R&D. Bootstrapping.
| ericyd wrote:
| Are you suggesting that creating a new programming language
| from scratch is a trivial exercise? If yes, wow. If no, I
| think the intention of your comment could be more clear,
| particularly regarding the quote you took from the original
| comment.
| couchand wrote:
| I suspect the GP was merely suggesting a less-costly
| alternative. Perhaps building a complete standalone
| compiler or interpreter is hard, but we're all designing
| APIs in our programming languange of choice day in and day
| out.
|
| Both strategies are very hard, but one of then is "build a
| prototype in a weekend" hard and one of them is "build a
| prototype is a month" hard.
| jacobr1 wrote:
| It is interesting to consider how much the lower
| abstraction influences the higher abstraction. If you are
| building on a existing language/runtime/framework then
| you can inherit more functionality and move faster, but
| also you implicitly will inherent many of the design
| decisions and tradeoffs.
| couchand wrote:
| Very good point. See, for instance Kiselyov's embedding
| of his tagless final form:
| https://www.okmij.org/ftp/tagless-
| final/course/lecture.pdf
| convolvatron wrote:
| totally. for me the interplay between the host language
| and the target language is hardest thing for me to manage
| when bringing up a new environment. it really doesn't
| seem like it should be a big deal, but it comes down to
| the sad reality that we operate by rote alot of the time,
| and completely switching semantic modes when going
| between one world and the other is confusing and imposes
| a real cost.
|
| I'm still not that good at it, but my best strategy to
| date is to try to work in a restricted environment of
| both the host and the target that are nearly the same.
| arethuza wrote:
| Creating a "new" programming language isn't _that_
| difficult - creating something that is interesting, elegant
| and /or powerful requires a lot of thought and _that_ is
| difficult.
| ericyd wrote:
| For me, creating a new programming language which is
| suitable for general purpose programming would be
| extremely hard, regardless of how novel or good it is.
| But, fair point that "hard" is always subjective.
| thesz wrote:
| Quite the contrary.
|
| You need to use existing facilities (type checking, pattern
| matching combinators, etc) of a good implementation
| language as much as possible before even going to touch
| yacc or something like that.
| pas wrote:
| Runtime would be nice, but ... that's basically what Tokio and
| the other async frameworks are. What's needed is better/more
| runtime(s), better support for eliding stuff based on the
| runtime, etc.
|
| It seems very hard to pick a good 'number' (JS's is actually a
| double-precision 64-bit IEEE 754 float, which almost never
| feels right).
| benrutter wrote:
| Yes, that's true - "number" is probably more broad than I'd
| really want. That said, python's "int", "float" and "decimal"
| options (although decimal isn't really first class in the
| same way the otherse are) feels like a nice balance. But
| again, its interesting the way even that is probably a bias
| towards the type of problems I work with vs other people who
| want more specification.
| jacobr1 wrote:
| The key though is probably to have a strong Number
| interface, where the overhead of it being an object is
| complied away, so you can easily switch out different
| implementations, optimize to a more concrete time at
| AOT/JIT time and have clear semantics for conversion when
| different parts of the system want different concrete
| numeric types. You can then have any sort of default you
| want, such as an arbitrary precision library, or decimal or
| whatever, but easily change the declaration and get all the
| benefits, without needing to modify downstream code that
| respects the interface and doesn't rely on a more specific
| type (which would be enforced by the type system and thus
| not silent if incompatible).
| mike_hearn wrote:
| That sort of stuff is easy to do with Truffle (which,
| ironically, lets you define a language using what they
| call the "truffle dsl").
|
| The SimpleLanguage tutorial language has a bigint style
| number scheme with efficient optimization:
|
| https://github.com/graalvm/simplelanguage/blob/master/lan
| gua...
| tialaramex wrote:
| "Number" implies at least the reals, which aren't
| computable so that's right out. Hans Boehm's "Towards an
| API for the Real Numbers" is interesting and I've been
| gradually implementing it in Rust, obviously (as I said,
| they aren't computable) this can't actually address the
| reals, but it can make a bunch of numbers humans think
| about far beyond the machine integers, so that's sometimes
| useful.
|
| Python at least has the big num integers, but its "float"
| is just Rust's f64, the 64-bit machine integers again but
| wearing a funny hat, not even a decimal big num, and
| decimal isn't much better.
| iopq wrote:
| I don't know why you think it implies reals. Most people
| would assume BigDecimal
| int_19h wrote:
| I would argue that what "number" implies depends on who
| you are. To a mathematician it might imply "real" (but
| then why not complex? etc), but to most of us a number is
| that thing that you write down with digits - and for the
| vast majority of practical use cases in modern
| programming that's a perfectly reasonable definition. So,
| basically, rational numbers.
|
| The bigger problem is precision. The right thing there,
| IMO, is to default to infinite (like Python does for ints
| but not floats), with the ability to constrain as needed.
| It is also obviously useful to be able to constrain the
| denominator to something like 10.
|
| The internal representation really shouldn't matter that
| much in most actual applications. Let game devs and
| people who write ML code worry about 32-bit ints and
| 64-bit floats.
| sanderjd wrote:
| In college, my programming languages class used a language
| called "Mystery" (I believe created by my professor), which was
| _configurable_. Assignments would be like "write some test
| programs to figure out whether the language is configured to
| use pass-by-value or pass-by-reference". And there were a bunch
| of other knobs that could be turned, and in each case, the idea
| was that we could figure out the knob's setting by writing
| programs and seeing what they did.
|
| I _loved_ this, both as a teaching aid, and as an eye-opener
| that programming languages are just an accumulation of choices
| with different trade-offs that can all go different ways and
| result in something that works, perhaps a bit better or perhaps
| worse, or perhaps just a bit more toward or away from one 's
| own personal taste.
|
| This is sort of the lisp idea of "create the language that is
| natural to write the application in, then write the
| application". Or Ruby's take on that idea, with more syntax
| than lisp but flexible and "human" enough to be DSL-ish.
|
| But somewhat to my sadness, as I've progressed in my career,
| I've realized that the flip side of this is that, if you're
| building something big it will require lots of people and all
| those people will have different experiences and personal
| preferences, so just picking one standard thing and one
| standard set of defaults and sticking with that is the way to
| go. It reduces cognitive overhead and debate and widens the
| pool of people who can contribute to your effort.
|
| But for personal projects, I still love this idea of thought
| experimentation around the different ways languages and
| programming environments could work!
| couchand wrote:
| Don't be so quick to discount DSLs. Sure, you don't want a
| half-baked DSL when some simple imperative code would do. But
| if you watch your API evolve into an algebra and then don't
| formalize it with a DSL you might be leaving powerful tools
| for understanding on the table.
|
| A poor-fitting language is terrible for abstract thinking, on
| the other hand an internally-consistent and domain
| appropriate language can unlock new ways of looking at
| problems.
|
| I'd highly recommend Martin Fowler's work on DSLs to see how
| you can apply these techiques to large projects.
| jacobr1 wrote:
| A related notion is that you need strong, well-thought out,
| and when the system is changing, regularly refactored
| abstractions. You might not need a DSL but your
| class/type/trait designs needs to be sane, your API needs
| to be solid, etc ... DDD principles are key here.
| couchand wrote:
| Yes, eat your vegetables!
|
| A question of philosophy: If you have all that, don't you
| already have a DSL, using a deep embedding in the host
| language?
| seanc wrote:
| I certainly think so. Or at least I find it very helpful
| to think about interface design that way. It's DLS's all
| the way down.
| jimbokun wrote:
| Yes, but the language in which you create your framework
| can do a lot of the heavy lifting. For example, if your
| main interface is a REST API, there is a large body of
| knowledge of best practices, educational resources, and
| existing tools for interacting with it.
|
| With a new DSL, you need to create all of that yourself.
| couchand wrote:
| The point I (and it seems several others here) are trying
| to make is that your API already is a DSL, the question
| is just whether it's a good one or a bad one.
|
| A good one is internally consistent so that users have
| predictability when writing and reading usage. A good one
| uses the minimum number of distinct elements required for
| the problem domain. A good one lets the user focus on
| what they're trying to do and not how they need to do it.
|
| The principles apply regardless of interface. Physical
| device, software UI, API, DSL, argument over HN, it's all
| a continuum.
| wredue wrote:
| The problem a lot of people have with DSLs is... well, just
| look at a prime example: SAS.
|
| If you're an experienced programmer coming in to SAS, your
| vocabulary for the next LONG time is going to consist
| primarily of "What The Fuck is this shit?!?"
| smallnamespace wrote:
| What do you mean? Computations very naturally organize
| into batches of 40 cards each.
| purist33 wrote:
| I hated SAS with a passion when I was forced to work with
| it for 2 years. One of the biggest problems I faced was,
| it would take me a long time to find out if something was
| doable or almost impossible in that language.
|
| It wanted to be more than just SQL, but the
| interoperability with other languages was awful, we
| couldnt even work with it like SQLite.
| rugina wrote:
| Given that the GitHub repo is almost three years old, I
| expect Martin Fowler to already have Dada Patterns,
| Refactoring in Dada, Dada Distilled, Dada DSL and Dada Best
| Practices ready to publish.
| jimbokun wrote:
| Yes, but then you need to be able to market your DSL and
| get buy-in. Otherwise you will forever be just a team of
| one. And then need to sell to all the stakeholders of the
| project the idea of trusting one person for all the
| development.
|
| So in addition to the skill of creating a DSL, you need the
| skills of thoroughly documenting it, training other people
| to use it, creating tools for it, and explaining the
| benefits in a way that gets them more excited than just
| using an existing Boring Old Programming Language.
|
| Which is certainly possible. You can get non developers
| excited if they can use it for answering their own
| questions or creating their own business rules, for
| example. But it's a distinct skill set from cranking out
| code to solve problems. It requires a strong understanding
| of the UX (or DX) implications of this new language.
| travisjungroth wrote:
| I'm of the mindset that API and DSL are more of a
| continuum than categories. As soon as you write your
| first abstraction, you're making a little language.
|
| In the same way, what you listed isn't a distinct skill
| set from cranking out code to solve problems. What
| happens is those skills are now levered. Not the good
| vibes "leveraged". I mean in the "impact to success and
| failure is 100x baseline" sense. If those skills are in
| the red, you get wiped out.
| couchand wrote:
| Every word you wrote is true. It's all still true if you
| replace "DSL" with any project and "Boring Old Language"
| with the competitor.
|
| This is the stopping at 90% problem somebody just posted
| a link to in another thread. edit:
| https://austinhenley.com/blog/90percent.html
| PretzelPirate wrote:
| Was your professor Amer Diwan? His Principles of Programming
| Languages course was amazing.
|
| This is one of his papers in Pl-Detective and Mystery for
| anyone interested:
| https://www.researchgate.net/publication/220094473_PL-
| Detect...
| sanderjd wrote:
| Yep :) I thought there would probably be some folks here
| who would recognize this.
| kant2002 wrote:
| Is this Mistery this Mistery [1]?
|
| [1] https://blog.brownplt.org/2018/07/05/mystery-
| languages.html
| sanderjd wrote:
| Nope, but if you click into their paper[0] and follow the
| link to PL-Detective[1] there, that's the one! (Hat tip to
| another commenter who was also familiar with this.)
|
| 0: https://cs.brown.edu/~sk/Publications/Papers/Published/p
| kf-t...
|
| 1: https://dl.acm.org/doi/10.1145/1086339.1086340
| samatman wrote:
| The gradual type systems you're referring to are bolted onto
| the languages, or in Elixir's case, the runtime. If you want to
| see what a language with a deeply integrated gradual type
| system is like, take a look at Julia. I've found it to be both
| expressive and precise.
| weatherlight wrote:
| Have you played at all with Gleam?
|
| https://gleam.run/cheatsheets/gleam-for-rust-users/
| hoosieree wrote:
| This was my first thought too. I've not used it (just clicked
| through the tutorial) but it has a strong flavor like "Rust,
| but pleasant".
| rayiner wrote:
| The challenge of thought experiments, in a statically typed
| language, is ensuring soundness. The first version of Java
| Generics, for example, was unsound:
| https://hackernoon.com/java-is-unsound-28c84cb2b3f
| jimbokun wrote:
| Isn't Rust a "high level rust"?
| obeavs wrote:
| For what it's worth, Moonbit (https://www.moonbitlang.com/) is
| a really nice take on this. Designed by the guys who created
| Rescript for OCAML, but for WASM-first world.
| Diris wrote:
| Wow, that's nice. I didn't know about that one. Thank you for
| posting!
| k__ wrote:
| Reminds me of Dyon, a scripting language for Piston.
|
| It's dynamically typed and uses lifetimes instead of a garbage
| collector.
|
| https://github.com/PistonDevelopers/dyon/issues/173
| dist-epoch wrote:
| > Dada is object-oriented, though not in a purist way
|
| Are classes cool again?
| speed_spread wrote:
| Only the upper ones.
| imjonse wrote:
| Not new, launched in 2021 apparently.
| luke-stanley wrote:
| I was posting that "a_print" (an auto running async printer)
| might be better for one of the most common features a programmer
| uses.
|
| I'm coming from Python, and for situations when people grasp for
| C/++ kind of performance and control, I think people are aware of
| the need for high performance memory safe languages that are
| easier to use than Rust but with many of Rust's benefits being at
| least possible. So I am quite excited by thinking from Dada and
| the people who are behind Rust and I'm also intrigued by
| SerenityOS's Jakt language project. I hope the insecure "C code
| problem" has a smooth migration path that let's C/++ devs,
| Typescript devs, and others make progress quickly in a powerful
| way. What other sort of alternative languages are there, among
| Dada's aspirations? Jakt? Vale (I understand a lead dev is
| poorly, so it's slowed a bit lately)? D? Go? Obviously AI will
| have a big impact. What language is going to have a big impact in
| this space?
| nu11ptr wrote:
| I like the idea, but please no "async/await". In a higher level
| language green threads like Go has are the correct answer IMO
| (and I'm not a Go fan, but I feel they got this part right).
|
| Gradual typing is interesting, but I wonder if necessary. Static
| typing doesn't have to feel like a burden and could make it hard
| to reason about performance. I think more type inference would be
| better than gradually typed (like OCaml/ML).
| jerf wrote:
| "Gradual typing is interesting, but I wonder if necessary."
|
| Open question: Are there any languages that can be used in a
| (decent [1]) REPL, that are strongly typed, but do not have
| Hindley-Milner-based type inference?
|
| We have multiple concrete proofs that you can have a REPL with
| Hindley-Milner inference, but I'm curious if this is perhaps a
| concession to the difficulty of a strongly-typed REPL without a
| deeply inferable type system. But it's just an idle musing I'm
| throwing out to see the response to.
|
| [1]: That is, for example, multiple people have put a Go REPL
| together, but anyone who has used a "real" REPL from the likes
| of Lisp, Haskell, Erlang, O'Caml, Python, etc., will not find
| it a "decent" REPL, as Go just can't have one for various
| reasons.
| naasking wrote:
| Scala has a REPL. It uses HM, but has limitations on type
| inference due to subtyping.
| munificent wrote:
| I'm not aware of any technical reasons why a given language
| would profoundly struggle to have a good REPL. I think it's
| mostly a matter of culture where REPLs aren't a priority in
| some language ecosystems because programmers there don't
| generally work that way.
| jerf wrote:
| I'm not immediately aware of one either which is why I
| asked. HM does have its advantages but static languages are
| generally pretty clear on the type of an expression without
| annotations and just giving a variable the type of what it
| is set to achieves most of what you're looking for. It just
| occurred to me I couldn't name an instance of a static
| language without HM that does that, though. (At least I'm
| assuming LISP REPLs generally operate dynamically.)
| munificent wrote:
| One thing that does make it kind of weird is that a lot
| of statically typed languages that aren't from the ML
| family have a grammar top level that isn't imperative. In
| C#, Java, Dart, etc. The top level of a source file is
| purely declarative.
|
| That can make a REPL sort of semantically weird. Do you
| allow variable declarations? If so, are they local or
| global? Do you allow class declarations in them? If so,
| can they access previous declarations?
|
| All of that's easier in a dynamically typed language
| where the top level of a program is more or less just
| regular imperative code.
|
| It's not insurmountable though, because you can be a
| little hand-wavey about semantics in a REPL if needed.
| mplanchard wrote:
| Personally I love explicit coroutines for their flexibility.
| It's great to be able to multiplex a bunch of IO bound
| operations on a single thread, defining some in chains and
| other to execute in parallel. It's great to be able to easily
| decide when I want to wait for them all to finish, to do
| something like `select`, or to spin them off into the
| background. Rust's ownership occasionally makes this a bit more
| of a challenge than I would like it to be, but I certainly
| wouldn't trade the ability for a more "convenient" syntax.
| jamsterion wrote:
| Dada looks "almost" great! I especially like that it targets
| wasm; I believe wasm is the future of frontend and also backend
| with wasi. However, I believe that being gradually typed is a
| mistake. Dart started being optionally typed and then they made
| it fully statically typed for very good reasons. I hope they
| learn from Dart's experience there.
| color_me_not wrote:
| I don't understand the comment in the method print_point in the
| class Point of the tutorial. [...] #
| This function is declared as `async` because it # awaits
| the result of print. async fn print_point(p) {
| # [...] print("The point is: {p}").await }
| [...]
|
| From the first page of the tutorial:
|
| > Dada, like JavaScript, is based exclusively on async-await.
| This means that operations that perform I/O, like print, don't
| execute immediately. Instead, they return a thunk, which is
| basically "code waiting to run" (but not running yet). The thunk
| doesn't execute until you await it by using the .await operation.
|
| So, what it boils down to is that async/await are like lazily
| computed values (they work a bit like the lazy/force keywords in
| Ocaml for instance, though async seems to be reserved for
| function declarations). If that is the case, that method
| "print_point" is forcing the call to print to get that thunk
| evaluated. Yet, the method itself is marked async, which means
| that it would be lazily evaluated? Would it be the same to define
| it as: fn print_point(p) {
| print("The point is: {p}") }
|
| If not, what is the meaning of the above? Or with various
| combinations of async/await in the signature & body? Are they
| ill-typed?
|
| I wish they'd provide a more thorough explanation of what
| await/async means here.
|
| Or maybe it is a dadaist[0] comment?
|
| [0] https://en.wikipedia.org/wiki/Dada
| couchand wrote:
| I suspect they're heavily relying on intuition coming from
| Rust, where both of those forms are okay. The one from TFA is
| sugar for your version. This works fine as long as there is
| only a single await point, otherwise you have to transform the
| syntax into a bind, which you might not be able to legally do
| manually (in Rust at least) if you hold a borrow across the
| await point.
| nialv7 wrote:
| I think they didn't do a very good job explaining it. Await
| doesn't just mean "please run this thunk", it means "I am not
| going to deal with this thunk, can someone come and take over,
| just give me the result in the end".
|
| What this means, concretely, in Rust, is `.await` will return
| the thunk to the caller, and the caller should resume the async
| function when the result is ready. Of course the caller can
| await again and push the responsibility further back.
|
| The most important thing here, is that `.await` yields the
| control of execution. Why does this matter? Because IO can
| block. If control wasn't given up, IO will block the whole
| program; if it is, then something else will have a chance to
| run while you wait.
| color_me_not wrote:
| So, you mean that this thunk is produced by the async
| function, and the await keyword will run it asynchronously?
|
| In other words, print produces a thunk, and print_point also
| produces a thunk, and when await is used on the later, it is
| executed asynchronously, which will execute the print also
| asynchronously. So we end up with 3 different execution
| context: the main one, a one for each "await"?
|
| What is the point of this, as opposed to executing the thunk
| asynchronously right away? Also, how does one get the result?
| ordu wrote:
| _> the await keyword will run it asynchronously?_
|
| From the point of view of print_point await executes the
| thunk synchronously, print_point execution stops and awaits
| for print to finish it work. But a callee of print_point
| might want it to run print_point asynchronously, so
| print_point is an async fn, and callee can do something
| more creative then to await.
| BobbyTables2 wrote:
| Sounds a bit like Python but with actual & optional runtime type
| checking?
| richrichie wrote:
| It was only a matter of time before even the creators of Rust
| grew tired of it being another C++.
| sorenjan wrote:
| Changing a quote to change "his" to "theirs" seem like a very
| Rust community thing to do.
|
| > Updated to use modern pronouns.
|
| https://dada-lang.org/docs/about/
| everybodyknows wrote:
| On iPad, I see a back-link from the footnote, but no forward
| link to it from the corrupted quotation.
| alphazard wrote:
| I also noticed this, along with the warnings that Dada doesn't
| really exist yet (which is fine, thanks for the heads up).
|
| I predict this project will have its priorities backwards.
| There's a group of people who want to govern a programming
| language project, and inject their ideology into that
| structure, and maybe there's another group of avid language
| designers in there too. I think there are more of the first.
| herval wrote:
| How do you "inject ideology" in a programming language?
|
| Compiler error if the variable name is sexist?
| alphazard wrote:
| > How do you "inject ideology" in a programming language?
|
| I was just talking about the project community and
| governance. It would be hard to imagine injecting ideology
| into the language itself.
|
| Oh wait, nevermind...
|
| https://doc.rust-lang.org/beta/nightly-
| rustc/tidy/style/cons...
| steveklabnik wrote:
| This is part of rustc's test suite. It affects nobody but
| rustc.
| travisgriggs wrote:
| Pournelle's Iron Law of Bureaucracy
| umvi wrote:
| Is it still a quote in that case?
| Hamuko wrote:
| I've understood that you can modify quotes but you have to
| indicate the bits that you've modified. So "It enforces
| memory safety" becomes "[Rust] enforces memory safety" if you
| want to modify a quote to make more sense out of context.
| tirpen wrote:
| Yes, it's just a different translation of the original French
| quote.
| ursuscamp wrote:
| As an avid fan of Rust, the Rust community is incredibly cringe
| about this topic.
| myko wrote:
| Seems more cringe to complain about pronouns
| zarathustreal wrote:
| I think we're all saying the same things here. No one wants
| to hear complaints about pronouns
| rob74 wrote:
| Actually, what I don't want is a discussion about
| pronouns being at the top of the comments. Aren't there
| more interesting topics to discuss about this project?!
| cmrdporcupine wrote:
| Indeed, far more annoying is that someone grousing about
| the TFA update about pronouns "seems like a very
| [subsection of] HN community thing to do."
|
| And yet here I am, N levels down in this thread, griping
| about it. Oops.
| javier_cardona wrote:
| Just for context, the quoted manifesto was originally written
| in French
| (https://monoskop.org/images/3/3b/Dada_3_Dec_1918.pdf). In that
| version, that particular sentence is gender neutral: "tout le
| monde fait son art a sa facon".
|
| I would say that that their updated quote is a more accurate
| translation of the original than the English translation they
| initially used.
| sorenjan wrote:
| That does make it a lot better, but at the same time makes
| the footnote even more of a deliberate statement that could
| have been left out.
| gr4vityWall wrote:
| > That does make it a lot better
|
| Why?
| OtomotO wrote:
| Non-native-speaker take: I don't care, it just reads a bit
| "weird" as I learned English before and "theirs" was plural...
| but I am adaptable.
|
| As long as the meaning of the quote isn't changed I couldn't
| care less and it seems very important to some people.
|
| What I personally dislike though is the whole "Ask me my
| pronouns" thing... like "No, I don't care about your gender or
| sex, as long as I am not interested in a romantic relationship
| with you - just tell me how to call you and I'll do it, but
| more effort? No!"
|
| To elaborate a bit more: I find the topic exhausting not
| because I hate freedom of choosing your own gender or anything
| like that, but because I personally do not care about your
| gender at all.
|
| I don't care about your religion, your skin color, your
| culture, your sex, your gender... I care about individual
| people but I don't reduce them to a certain aspect of their
| existence.
|
| Now I find the whole "Ask me my pronouns" exhausting and also
| rude because it puts pressure on me to ask you about a topic I
| am not interested in. Like: I get it, there is social pressure,
| I understand that you're not happy with certain social "norms"
| and developments. I totally get that and I guess we are on the
| same side for many of them, but I still do not care about your
| gender until I care about your gender. (And also, I don't live
| in your country probably, so your local politics may be of
| interest, but I still don't like being forced to talk about
| them before I can ask a genuine question on e.g. a technology
| topic ;))
|
| Just write his/her/theirs... and I will respect your choice. I
| will not think less of you, nor will I put you on a pedestal
| for something I do not care about.
| rob74 wrote:
| The "singular they" has been a thing in English for a long
| time (since the 14th century according to Wikipedia -
| https://en.wikipedia.org/wiki/Singular_they). I'm a non-
| native speaker as well, and wasn't taught about it in school
| either (maybe that has changed in the meantime?). The first
| time I consciously noticed it is probably in the Sting song
| _If You Love Somebody Set Them Free_ (https://en.wikipedia.or
| g/wiki/If_You_Love_Somebody_Set_Them_...), which was his
| debut solo single, so is already quite old itself (1985,
| although I probably heard it later).
| moomin wrote:
| Yeah, it's been commonly used when the object (in the
| grammatical sense) would typically have a gender but it is
| unspecified. In fact, it's so common native English
| speakers don't even notice they're doing it. (Which
| produces a steady stream of unintentional humor from those
| pretending it isn't a thing.) The usage as a sign of
| respect for specific non-binary and other gender non-
| confirming people is more modern (2009 is apparently the
| first recorded example). Although to a great extent, it
| doesn't matter. Language evolves over time and dictionary
| definitions necessarily trail usage.
|
| The wikipedia article is quite detailed and will probably
| supply more information that anyone particularly wanted.
| https://en.wikipedia.org/wiki/Singular_they
| timeon wrote:
| There is also "singular you" in English.
| yodsanklai wrote:
| > Non-native-speaker take: I don't care, it just reads a bit
| "weird" as I learned English before and "theirs" was
| plural...
|
| Non-native speaker too, I find it easier to adjust in English
| compared to my native language (French), probably because the
| language is less engrained in me. I embraced the English
| neutral pleural - it's even convenient - but I found myself a
| bit more annoyed with the so called French *ecriture
| inclusive", such as "les etudiant.e.s sont fatigue.e.s". Not
| really pretty IMHO. We could find something better..
| dist-epoch wrote:
| > I learned English before and "theirs" was plural..
|
| Its been done before. See royal plural
|
| https://en.wikipedia.org/wiki/Royal_we
| OtomotO wrote:
| Pluralis Majestatis exists in my mothertongue too ;)
| subtra3t wrote:
| People who want others to ask them their pronouns before
| referring to them, what is your reason for doing so?
| tialaramex wrote:
| I mean, Tristan Tzara is Romanian and so it seems likely that
| this thought isn't originally English anyway, so it's
| reasonable for a modern writer to choose to translate it in a
| more inclusive way. I expect that an early English Bible and a
| modern one likewise make different choices about whether a text
| that's clearly about people generally and isn't concerned with
| sex or gender - should say "He" or "They" / "His" or "Their"
| and so on.
| twic wrote:
| Changing it is perfectly reasonable, but specifically
| advertising that you've done it in a footnote is extremely Rust
| community.
| winwhiz wrote:
| It is also a very Dadaism thing to do. Da!
| mplanchard wrote:
| The policing of what other people should or shouldn't care
| about or advertise they care about is very boorish to me, but
| of course here I am doing the same thing.
| timeon wrote:
| > modern pronouns.
|
| In my native language it is quite old-school. Really polite
| form.
| kwhitefoot wrote:
| Singular they and their is six centuries old in English.
| bmitc wrote:
| I thought the creators of Rust were _creator_ , singular, in
| Graydon Hoare. Are they involved with this?
| steveklabnik wrote:
| Graydon does not have any commits in the repository.
| estebank wrote:
| Niko has been involved with Rust since before they had
| conceived of the borrow checker and the entire commiter list
| could be fed with a pizza.
| bmitc wrote:
| I would distinguish creator(s) from early key contributors
| and developers. I'm not aware of the full history of Rust but
| was under the understanding that Graydon Hoare is the creator
| of the language.
| talkingtab wrote:
| My opinionated opinion: programming languages have three goals.
| 1) Be safe, don't make mistakes 2) Be expressive: The Sapir Whorf
| hypothesis 3) Be easy to use.
|
| JavaScript (new) is +++2, and ++3 (to me). Java is +++1 & --2,
| -3.
|
| Personally I like OO ("has a") but think Class-ification,("is a")
| is a big mistake. Take a truck and a car. Start replacing the
| pieces of the car with pieces from the truck. When is a car not a
| car? Arbitrary. When does the car have a tail gate, a flat bed?
|
| That is not a joke. Classes and Types are a way to think (Sapir
| Whorf) that makes you do strange things.
|
| The interesting thing about Dada is the "borrow", "share" etc and
| seems very good. But then instead of wrapping it in a class can't
| we just use an Object?
| mihaic wrote:
| I've written a bit of Rust, and I was left with mixed feelings,
| that seem to be still the same here: - loved the memory safety
| patterns when compared to the horrible things that you can do
| with C++ - found almost every thing where it was different to
| have a harder to parse syntax, that I could never get used to.
| The implicit return at the end of a statement for instance make
| it harder for me to visually parse what's being returned, since I
| really depend on that keyword.
|
| Code in general is hard for me to mentally read. I know it sounds
| nitpicky, but to me all keywords should be obviously
| pronounceable, so something like "func" instead of "fn" would be
| mandatory. Also, using the permission keywords where I'd expect
| the type to be also seems a bit strange, as I'd imagine that
| keyword to prefix the variable -- that's just how I think though.
|
| It does seem like less decorator magic and symbol-based syntax
| would make it easier for beginners to grasp.
|
| I may sound like a curmudgeon, but I'd prefer only one type of
| language innovation at a time.
| haswell wrote:
| I'm in the middle of working through The Rust Book, and I
| haven't written any serious code with it yet, so interpret this
| through that lens.
|
| When I looked at rust code before, it all seemed a bit weird. I
| couldn't immediately understand it, but I've since come to
| realize this was because the dozen or so languages I can read
| well don't really resemble rust, so my pattern matching was a
| bit off.
|
| The more I learn about the syntax and core concepts, the more
| I'm learning that my brain absolutely loves it. Once I started
| to understand matches, lifetime syntax and the core borrowing
| mechanics, things clicked and I'm more excited about writing
| code than I've been since I taught myself GW-BASIC 25 years
| ago.
|
| Just sharing this anecdote because I find it interesting how
| differently people experience languages. I also have an ongoing
| friendly debate with a friend who absolutely hates Python,
| while I rather enjoy it. I've tried to understand why he hates
| it, and he's tried to understand why I like it. And it all
| seems to come down to hard-to-define things that just rub us in
| different ways.
|
| I hope the benefits of rust find their way into more types of
| languages in the future.
| mihaic wrote:
| Yeah, I think at some point we all have some internal wiring
| that is hard to change, while other parts are flexible.
|
| For instance, I'm fine to write C++, Javascript or Python
| (with types at least). Ruby or Rust for some reason do rub me
| the wrong way, no matter how much I try to tough it out.
| bmitc wrote:
| > The implicit return at the end of a statement for instance
| make it harder for me to visually parse what's being returned,
| since I really depend on that keyword.
|
| Cutting my teeth on Schemes and MLs and now working in Python,
| I have the complete opposite experience. It's jarring to have
| to specify return. What else would I want to do at the end of
| an expression? It seems tautological. The real reason it's
| there in Python is early return, which is even more dangerous
| and jarring.
| mihaic wrote:
| I know it's not very FP, but you might explicitly not want to
| return anything and just modify the data.
| bmitc wrote:
| That's perfectly acceptable and expected. F# supports OOP
| and imperative just as much as it does functional
| programming. In the case of such functions and expressions,
| the value returned is of type `unit` with a single value of
| `()`. In F#, expressions that return `unit` have the value
| explicitly ignored if they are not the last expression in a
| code block. Other expressions returning non-`unit` values
| that aren't at the end of an expression will generate a
| warning. In such cases, for example where a function
| performs a required side effect and returns a value other
| than `()` but you don't need that value, you can use `|>
| ignore` to get rid of the warning since it says you are
| explicitly wanting to ignore the returned value.
| mattgreenrocks wrote:
| Give it time. The syntax differences are real, but not
| insurmountable. I grew to prefer the location of the return
| type in function syntax despite having 15 years of C++ under my
| fingers.
| 4star3star wrote:
| > all keywords should be obviously pronounceable
|
| I hear you. Internally, I always pronounced "var" as rhymes
| with "care", but then a colleague pronounced it "var" as rhymes
| with "car". I think the same guy pronounced "char" like char-
| broiled, whereas I had thought of it like "care". And he would
| say "jay-SON" for json, which I pronounced like Jason.
|
| How would you feel about a notation that is not meant to be
| pronounced at all?
|
| +Employee {
|
| }
|
| where + indicates a class definition.
|
| :Rename() where : indicates a class method.
|
| ~DoStuff() where ~ indicates a static function
| mihaic wrote:
| Interesting, for all the examples you gave, I'd prefer to see
| a keyword, since you'd need to use a lot of symbols for a lot
| of different things in this way. I do find arrow notation or
| other symbol for lambdas fine, since it's a unique case and
| not a generic type of using symbols for keywords.
| naasking wrote:
| > Code in general is hard for me to mentally read. I know it
| sounds nitpicky, but to me all keywords should be obviously
| pronounceable,
|
| Have you tried Ada?
|
| > so something like "func" instead of "fn" would be mandatory.
|
| What about no keywords, like: x => ...func
| body
| mihaic wrote:
| > Have you tried Ada?
|
| I have tried Pascal in that sphere, which was on the too
| verbose side.
|
| Arrow notations like in JS/Typescript are fine to parse for
| me. Some clear symbols are actually easier to read than an
| unpronounceable alphanumeric.
| int_19h wrote:
| IMO the main thing that made Pascal verbose is begin...end
| for all compound statements. If you ditch that - as even
| Wirth himself did in the next iteration, Modula-2 - the
| rest is much more palatable. Consider: (*
| Pascal *) if a > b then begin
| blah; blah; end else begin
| blah; blah; end; -- Ada
| if a > b then blah; blah; else
| blah; blah; end if; // C
| if (a > b) { blah(); blah(); }
| else { blah(); blah(); }
|
| Pascal is clearly very verbose here, but the other two are
| pretty similar.
|
| That said I think that punctuation to delimit blocks makes
| more sense because it makes program _structure_ clearly
| distinct. Although by the same token I think I 'd prefer
| conditionals and loops to also be symbolic operators, so
| that there are no keywords inside executable code, only
| identifiers. Basically something like "?" instead of "if",
| "@" instead of "while" etc.
| zozbot234 wrote:
| {} are isomorphic to 'begin' and 'end' in that snippet,
| though. Part of the reason why early programming
| languages were comparatively heavy on keywords is that
| the symbol set was not standardized across machines, so
| you couldn't count on some symbols being available. It's
| why C still supports <% %> as digraphs for curly braces,
| or <: :> for square brackets. Also why languages such as
| COBOL go as far as supporting syntax like DIVIDE X INTO
| Y, because the machine character set might not _have_ a
| slash or divide sign.
| ordu wrote:
| _> I know it sounds nitpicky, but to me all keywords should be
| obviously pronounceable, so something like "func" instead of
| "fn" would be mandatory._
|
| Keywords only? How about function names like strspn or sbrk?
| And how do you feel about assembly language, using mnemonics
| like fsqrt or pcmpeqd?
|
| BTW, thinking about it, I notice, that I need all these lexemes
| to be pronounceable too, and I have my ways to pronounce sbrk
| or pcmpeqd. Probably if I do it aloud no one will understand
| me, but it doesn't matter because these pronunciations are for
| internal use only.
| mihaic wrote:
| I'm not sure how many codebases started after 2010 I've seen
| that have "pcmpeqd" as a method name. This is something I
| think makes sense only in highly optimized code, but in
| business logic it's a pain to read.
| owenbrown wrote:
| Every time I see a new language, I immediately check if it uses
| significant white space like Python. If it doesn't, I sigh sadly
| and dismiss it.
| csjh wrote:
| Why?
| RamtinJ95 wrote:
| This is such a weird take... I just want to know why is that SO
| important to you? For me that is one of the things that I like
| the least with Python.
| diggan wrote:
| Curious, I have the very opposite reaction, although I tolerate
| Python, but only for the massive amount of libraries and huge
| community. But as a language? Meh
|
| What makes you so reliant on significant white space that any
| language without is a automatic dismissal?
| udev4096 wrote:
| Not this again. How many languages do we need? I am having a good
| time with Go and Python!
| Georgelemental wrote:
| See also Graydon Hoare's Rust-that-could-have-been:
| https://graydon2.dreamwidth.org/307291.html
| pxeger1 wrote:
| I think there isn't enough research into languages with
| affine/linear typing (the property of some types that they can't
| be copied - which is partly what the borrow checker ensures in
| Rust). I'm super sold on it for enhancing safety. Vale with its
| "Higher RAII"[0] is the only other example I was aware of until
| seeing this.
|
| Rust is great but being an early adopter has made its usability
| imperfect in places. Combining substructural typing with gradual
| typing and OOP is interesting here. Others in this thread have
| also mentioned wanting a higher-level Rust, like Go. I'd like to
| see a purely functional Rust. Haskell has experimental support
| for linear typing[1], but I suspect a language built with it from
| the ground up would be very different.
|
| [0]: https://verdagon.dev/blog/higher-raii-7drl
|
| [1]:
| https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/line...
| magnio wrote:
| Have you look at Austral?[0] It is a system language with
| affine type as the main selling point. I really, _really_ like
| its specifications, in particular the design goals and
| rationale.
|
| [0]: https://austral-lang.org/
|
| [1]: https://austral-lang.org/spec/spec.html#goals
| ubj wrote:
| Interesting, but the intent seems similar to Chris Lattner's new
| Mojo language which arguably has similar characteristics and is
| further along in its development.
|
| https://docs.modular.com/mojo/
| melodyogonna wrote:
| Mojo but for Javascript
| stephen wrote:
| If you're cloning parts of TypeScript, please bring along mapped
| & conditional types!
|
| Feel free to experiment on the syntax, but the concept is
| amazing, especially if you're planning on being dynamic-ish.
| p0w3n3d wrote:
| It sounds like mockups to create a programming language
| greenie_beans wrote:
| love this quote
|
| > I speak only of myself since I do not wish to convince, I have
| no right to drag others into my river, I oblige no one to follow
| me and everybody practices their art their own way.
|
| > Tristan Tzara, "Dada Manifesto 1918"
| snarfy wrote:
| It's a bit frustrating that I have to click around hunting for an
| example of the syntax.
|
| If you are making a new programming language, please do us a
| favor and put your Hello World syntax example right on the
| landing page.
| platz wrote:
| I thought the docs themselves were a work of conceptual art
| i.e. the docs themselves were "dadaist" and were the main point
| of the site
| kkukshtel wrote:
| Feel like there would be fewer posts and languages like this if
| people just took 10 seconds to read about modern C#.
| iopq wrote:
| If only it played well with Linux, but Mono is always playing
| catch-up
| hgs3 wrote:
| I've dabbled in PL research before, and not to downplay the work
| as this is just my opinion, but the Rust ownership system is too
| invasive. It prevents entire classes of architectures and
| algorithms from being directly represented without auxiliary
| structures and other code contortions. I don't think it is an
| approach that should be mimicked.
| zozbot234 wrote:
| The Rust ownership system was built to be compositional - an
| architecture or algorithm must not just be "safe" in isolation,
| it must also preserve that safety when interacting with the
| rest of the system, even as either part gets modified or
| evolves further. Practically speaking, this is where many
| proposed architectures that may indeed appear "safe" run into
| issues. (If you can't provide these guarantees, the idiomatic
| approach in Rust is to isolate that part within an unsafe
| module, and document the expectations that said module imposes
| wrt. the rest of the system.)
| zubairq wrote:
| Amazing way to test if a new computer language is viable! I think
| that more people (including myself) should take this approach to
| language design.
| sn9 wrote:
| This might be a naive question, but rather than targeting WASM
| directly, why not target MLIR (used by projects like Mojo) and
| use LLVM to compile to WASM?
___________________________________________________________________
(page generated 2024-03-06 23:01 UTC)