About V, the language Volt is written in
volt.ws
volt.ws
Developer here. I was going to post this here in a couple of weeks after launching the product and creating a separate site for the language with much better information about it.
I'd also like to hear your opinion about not allowing to modify function arguments except for receivers. This is an idea I got that isn't really implemented in any language I know of.
For example: mut a := [1, 2, 3]
So instead of multiply_by_2(&a)
we have to return a new array (and this will later be optimized by the compiler of course)
a = multiply_by_2(a)
I think this will make programming in this language much safer, and the code will be easier to understand, since you can always be sure that values you pass can never be modified.
For some reason all new languages like Go, Rust, Nim, Swift use a lot of mutable args in their stdlibs.
You can still have methods that modify fields, this is not a pure functional language, because it has to be compatible with C/C++:
fn (f mut Foo) inc() { f.bar++ }
This probably means lots of aliasing restrictions or in the case where the optimization can't be done, copying could be an expensive side effect of an innocent refactoring.
I hear Swift uses something like this, though it's copy-on-write. I've not used Swift in any significant capacity. Does anyone else have experiences to share with this model?
A good way to imagine this is having return value optimizations give you a copy which is placed on the original which allows the work to be skipped. But that can require a whole lot of other trades around calling conventions, optimization boundaries and so on. C++ has dealt with some of this complexity recently but it’s nuances too years to sort out between standard revisions and only became required in some cases rather than legal until after compilers had plenty of time to work on it.
x := &a
a = sort(a)
print(x) // Sorted?
To detect whether something can be mutated in place will require static analysis to see if there are aliases or pointers to the data. If this is an optimization that's based on whether something is safe to mutate in-place, you'll run into the problem where performance becomes different depending on whether something can be optimized or not. For example, adding "x" makes the sort call suddenly perform worse since the compiler sees that it can't mutate "a" in-place.This is assuming that you allow multiple aliases to the same data. The reason Rust has lifetimes and borrowing is precisely to be safe about mutation. Rust wouldn't allow sort() to modify "a" in-place in the above code.
And you probably want to pick one of sorting in-place and out-of-place.
I say "rule of thumb" and I mean it that way. Sometimes there will be Haskell-specific answers. But if your programming language has less code metadata available than Haskell but is promising more optimizations, it's worth a cross-check. I agree with you strongly in this particular case; without type system support for this specific case, it's going to be very hard to optimize away things like a sort. You start getting into the world of supercompilation and whole-program optimization, the primary problems of which for both of them is that they tend to have intractable O(...) performances... but something about them makes them seem intuitively easy. I've seen a number of people fall into that trap.
(I haven't personally, but I understand the appeal. My intuition says they shouldn't be that difficult too! But the evidence clearly says it is. Very, very clearly. We're talking about things like optimizations that are super-exponential in complexity, but seem intuitively easy.)
I think you're right that it can often be an antipattern. But there are also use cases (usually for performance reasons), and the real problem occurs when you are not expecting the modification to happen. If the parameter is annotated then it's obvious that it might be mutated, and less of an issue...
P.S. Looking forward to the open source release. This langiage looks pretty nice/interesting to me, but there's no way I would invest time into learning a closed source lanaguage.
I had a small page about the language up. I don't have some of the most basic things implemented and figured out yet.
I can’t think of any well-known newish language (created in the last 10 years, say) with multiple implementations. Rust, Kotlin, Swift, Julia, Dart... any others?
Go might be a counterexample with its cgo implementation, but that was built by the same team and I have the impression (maybe mistaken) that it’s fallen by the wayside.
I don’t know if this indicates a really new language development style, with less emphasis on specification, or if it’s just a cyclic thing and some of these new languages will gain more implementations as they get more established.
Perhaps only Golang (go and go-gcc).
For all others, everybody uses the standard compiler. Even in Python, PyPy is not even 10% of the users.
Whereas in C/C++ and other such older languages there are several implementation (MS, GCC, LLVM, Borland, Intel) with strong uptake and strong communities/companies behind them.
It's way harder to develop tooling for a language which is only defined as "what its compiler can compile".
> It seems easy to accidentally make allocating code allocate by changing some variable names (b = fnc(a) - oops, allocation)
> I would be extremely wary of trusting a compiler to realize what sort of allocations are optimizable and not - I already have problems with inlining decisions, poor code layout, etc in fairly optimized c++/rust code compiled by gcc+llvm.
Replace allocation with any other expensive work that duplicating a datastructure would result in, and you have the same story. I suspect many of the people that would be evaluating this compared to C/C++/Rust have similar performance concerns.
Playing a game without accept its self imposed restrictions whose player accepted voluntarily would be lying to oneself.
> This is an idea I got that isn't really implemented
> in any language I know of.
Is this different than an arg declared as a const reference in C++. Or since fields are still mutable, like `final` arguments in Java? STRUCT (INT x, y) z = (1, 2)
Here z is a const struct. If you wanted a variable, you'd have to say STRUCT (INT x, y) z;
z := (1, 2)
or equivalently REF STRUCT (INT x, y) z = LOC STRUCT (INT x, y) := (1, 2)
Basically a variable has a REF mode.Overall if you don’t know Ada I’d recommend that you take a look at the features of it. It has very similar design goals as your V.
Do not underestimate this part. It can take a surprising amount of effort to get these things right and performant.
a) how do you plan to do this?
b) will the optimization still kick in if you name the return value something else than “a”?
c) what if “a” is an argument passed to the function that calls “multiplyBy2”? Then doing an in-place update would modify the value of “a” for some other function that has also been passed “a” as an argument.
I do wish the author the best with this project though. Plus designing your own language is fun :)
Thank you for replying :)
There's a false dichotomy between functions and methods, which are simply (sometimes dynamically dispatched) functions with a special first argument. If you allow mutable first arguments, why not any argument?
Instead of the language deciding what's mutable and not, I'd rather have a const system like C/C++ to ensure that changes aren't happening behind the programmer's back.
Re: "not allowing to modify function arguments except for receivers" -- maybe instead all fields const by default, but having something like an optional mut modifier?
A quick question, how does hot reloading work (with presumably AOT compilation and no runtime)?
(Perhaps there's a OS mechanism to change already loaded code in memory that I should know).
Both Rust and Swift require specifically opting into parameter mutation (respectively `&mut`[0] and `inout`) and the caller needs to be aware (by specifically passing in a mutable reference or a reference, respectively), only the receiver is "implicitly" mutable, and even then it needs to be mutably bound (`let mut` and `var` respectively).
Inner mutability notwithstanding, neither will allow mutating a parameter without the caller being specifically aware of that possibility.
The ability to mutate parameter is useful if not outright essential, especially lower down the stack where you really want to know what actually happens. Haskell can get away with complete userland immutability implicitly optimised to mutations (where that's not observable), Rust not so much.
[0] or `mut` in pass-by-value but the caller doesn't care about that: either it doesn't have access to the value anymore, or it has its own copy
So I would say that having to explicitly mark function parameters as mutable (like in Rust) is a better approach.
Why not go the other way and pass everything as a reference? After all that's what Java does, and that's how you'd pass any struct in C anyway. It's a rare case when I need to forbid the calling function to not modify an argument for whatever reason or because I don't trust it - in that case you can make a copy beforehand or use a const modifier. But in most cases I'd expect functions to modify the memory that I pass in, instead of allocating and returning new structures.
Why not have a simple `class` construct as in JavaScript? Keeping functions together in a class is very convenient and means you don't have to pass the struct as the first argument each time. That way `Array` can be a class, and would always be passed by reference. No ambiguity there, class instances are always mutable. Everyone is already familiar with it, it works.
A class method can simply map to a global C function: ``` ClassName_MethodName(*self, ...) ```
As an aside, using a syntax that people are already familiar with (and APIs!) would be great, and make something like this instantly usable. JavaScript has a fairly small core API which would be easy to emulate for example.
This already seems to have a way to associate functions with data structures, in the same way that methods are done in Go, via a "receiver" before the function name
Eg.
type Something{}
fn (self mut Something) method() { ... }
and calling the method with an instance x := Something{}
x.method() object = object._replace(foo=1)
But I usually encapsulate the _replace call in the class so it's more like: object = object.update_foo(1)
I personally find it can make the code easier to understand, like you say, but it seems like you're getting a lot of disagreement from the other comments.The disagreement they're getting is not on the use of immutability and pure transformations, it's on the fantasy that a "sufficiently smart compiler" would be able to optimise this (especially non-trivial versions of this) into mutations under the cover.
Furthermore, V is apparently supposed to be a fairly low-level language, if you have to rely on the compiler to perform the optimisation, can't statically assert that it does so[0] and it fails to, that is extremely costly in both "machine" time and "programmer" time (as you'll start wrangling with the compiler's heuristics to finally get what you need).
If you want immutability, do it, but do it properly: build the runtime and datastructures[1] and escape hatches which make it cheap and efficient, don't handwave that the compiler will solve the issue for you.
[0] and if you are you may be better off just adding mutation to the language already
[1] non-trivial immutable data structures are tree-based and translate to a fair number of allocations, you really want an advanced GC
This looks like a really interesting project, and I look forward to trying it out!
That's a solved problem, the "random blobs" is called a tuple. Or, since the language is inspired by Go, you can have bespoke multiple return values instead of a reified generic structure.
Direct compilation to x86-64 machine code does not get you performance on par with C (by which I assume the author means GCC or Clang). The optimization pipelines of GCC and Clang have had decades of work put into them by some of the best compiler engineers in the world.
Since the author states that the compilation time is linear, this would seem to imply that a full suite of optimizations are not being done, since many optimizations done by GCC and Clang have nonlinear complexity. It is easy to get fast compilation if you don't perform optimizations.
> - Thread safety and guaranteed absence of data races. You no longer have to constantly ask yourself: "Is this thread safe?" Everything is! No perfomance costs either. For example, if you are using a hash map in a concurrent function, a thread safe hash map is used automatically. Otherwise a faster single thread hash map is used.
This description doesn't guarantee freedom from data races. (Java's memory model basically fits this description, for instance, except for the specific case of hash tables, which aren't built into the language.) Even if it did, the tricky part is determining what a "concurrent function" is. The obvious ways one might imagine doing this tend to fall down in the face of higher-order functions.
Just updated it:
> V is compiled directly to x86_64 machine code (ARM support is coming later). There's also an option to generate C code to support more platforms and achieve better performance by using sophisticated GCC/clang optimization.
I want every part of the language ecosystem to be simple so that everyone can contribute.
"V has no runtime". No GC, but you don't have to manually release memory, like Rust but much easier. Sounds great. How?
And "no race conditions ever" and "everything is thread safe". You can do that with "no runtime" fairly easily if there's no goroutine-style concurrency. I didn't see any mentioned, but I could have easily missed it.
Those two aspects of the language are fundamental enough that I would certainly want to read about them near the top of any overview of the language.
That description could fit Fortran 77.
I want to do something similar to Rust's approach, but much much simpler. It's not an easy task.
Right now the language handles very simple cases. Small strings are placed on the stack, local variables that are not returned are clean up automatically.
Globals are not allowed, function args can't be modified, so that helps a bit.
To me the central concurrency scheme is one of the defining features of a modern language. Go and goroutines, ES/Node and event-driven paradigms, Java and threads... That does not mean a language can't handle many types of concurrency, but it's good to be opinionated on a preferred concurrency scheme from the get-go and have native methods for dealing with intercommunication (ie. Go's channels).
This strategy is time-honored in the Lisp world, where making a language and writing a program are more intertwined, and the cost of making a language much lower, than they usually are.
The software ecosystem is not well served by everyone being focused on the same few familiar programming approaches. Sure there are economies of scale—better tooling, programmer fungibility—but there is less intellectual diversity. More people should realize the tradeoffs here: yes you lose a lot when you start making your own language, but you also gain a lot. The program you're trying to write becomes more writeable. If that doesn't sound significant, it's because we're so conditioned to think the other way. There's another advantage, too: it's deeply intellectually rewarding. That provides staying power to work on significant projects over the long haul and is a solid motivation to do something many people think is crazy.
Then it seems that the problem has more to do with political economy than with programmer culture. Capital and managers want programmers to be cogs, not artisans.
Can’t expect programmers to change this political problem, either. Especially considering that the nerdier the technologist, the less political he or she is.
That and Maude is another fascinating language. Pure term re-writing and explicit definitions of all data structures seems almost like a higher level of abstraction or programming.
I think one of the issues of Gnome Project is this, they use a language specifically designed for Gnome/GTK+ and as if that was not enough, it has two different syntax, one--Vala which is sort-of-kind-of C#-like and the other being Genie which is sort of kind of python-like.
> There's also an option to generate C code to support more platforms and achieve [(possibly)] better performance
Another reason x-compilation to C matters: providing an escape in case the community thins out and no further updates are made on the V lang.
For instance here's what the chicken scheme transpiler outputs when told to compile a simple '(print "Hello, world!")': https://gist.github.com/simias/c96408a76eb7288fbd0d975f5dc99...
Good luck maintaining that...
I suspect you already know this, but for the benefit of others.
fn main() { println('hello world') } ==>
int main() { printf("hello world\n"); return 0 }
Only if your language (and standard library) is of comparable complexity to that of widespread languages. C has more quirks than it lets on, C++ is a monstrously complex beast, Java has an enormous standard library…
If however you keep the syntax and semantics of your language simple, they can be learned in a matter of minutes. If you keep the "standard" library focused towards your application, it won't require more effort than any other regular application.
The real problem with custom languages, I think, is that very few programmers can actually write one. Most others don't even see the need, I think in part because of motivated cognition (If I delude myself into thinking I don't need something, I don't have to face the fact that I can't do it). Though the main problem is probably education: we are taught that languages are chosen, not made. As for how they are made… well, that's the realm of geniuses who have way too much time to spare.
Every programmer should have an introduction to programming languages, and we need more specialists who can whip up a DSL in a couple days. Our craft would be very different (and I think much better) if we did that.
Rebol / Red
NB. Here's an old Wikipedia link listing (some) languages that were good for creating dialects (DSLs) - https://web.archive.org/web/20140708161345/http://en.wikiped...
It's fairly trivial to expose C++ libraries to any other language context, IFF the library is wrapped to a DLL that respects the C ABI. The reverse is not true. You need to have some message passing mechanism in that case (yes, there are several not-so-hard ways to do that but that again, is added complexity).
Yes, and building a library (a DSL) in an existing powerful language that can do it (and there are many as people said in this thread) for exactly what you need, is _vastly_ simpler than making a new language toolchain (which linker? which codegen? which typing?).
A stack based language like forth would be even less work.
Functional programming, especially Haskell, tends to use the term 'embedded domain-specific language' ( http://wiki.c2.com/?EmbeddedDomainSpecificLanguage )
Lisps tend to call them DSLs or sometimes "mini languages"
Forth calls them "vocabularies"
Couple of other terms i've seen...
* Pidgin - An attempt to get away from DSL ambiguity!
* Slang - This is what Perl6 calls them
(Lisp) "dialect" seems to refer to a particular implementation/variant of Lisp, e.g. CommonLisp, Scheme, Racket, Clojure, MacLisp, NewLisp, etc. rather than a domain-specific language built in a Lisp.
(e.g. searching for "lisp dialect" gives pages like https://www.slant.co/topics/5928/~lisp-dialects )
Also, once you understand the problem space well enough, a custom syntax can be a nice bonus.
I don't how many other languages started like that. PHP for one. Probably a lot.
http://www.math.bas.bg/softeng/bantchev/place/erlang/a-histo...
Erlang is still a niche.
Both are examples of confirmation bias. There is a massive graveyard of one-man languages that no one used and then died.
The genius of PHP was in the code delivery model and the way you could intermix HTML and code in a single page to be served by Apache.
That democratized Web programming and programming at large. The rest of the language was bad, but it didn't matter for success (see "worse is better", where "better" means fitter for the market).
I wish programming languages made a type-level distinction between strings that are and aren't tainted by user input. That would make it so much harder to accidentally introduce injection vectors.
I totally agree that PHP was not well suited for writing large and complex programs, but its ubiquitous availability as a deployment platform made it an interesting target anyway.
The easy deployment also made it easy for people to learn it by themselves, and consequently there was a large pool of programmers who knew PHP, making it an interesting language from a hiring point of view.
And that's how we ended up with piles of crappy, proprietary and OSS PHP code in the wild. The quality of the language is only a minor factor its success.
This is an important point that is still underappreciated even today with all of our hindsight.
I was just trying to think of (well-known) languages written that way. I guess there've been just as many dead languages not written with a particular program in mind.
One example of this is video game designer and programmer Jonathan Blow, best known for creating the game Braid.
https://en.wikipedia.org/wiki/Braid_(video_game)
He's working on a language for writing games.
https://www.gamesindustry.biz/articles/2018-07-02-jonathan-b...
https://www.reddit.com/r/programming/comments/7okvam/jai_lan...
https://www.reddit.com/r/programming/comments/8ywd77/gamelab...
https://www.reddit.com/r/programming/comments/89209l/jonatha...
Here is one of many videos of him using the language:
https://www.youtube.com/watch?v=AAFkdrP1CHQ
A couple of moments in that video which I would like to highlight:
At 11:15, responding to a question from chat:
> Is there a specific reason the game is kind of in top-down 3D?
> Because that is what helps the game mechanics that we need for this game. If it was in first-person (laughs)... it would be kind of amusing... maybe we should do that (smiles) that'd be fun.
At 14:05, responding to another question from chat:
> Do I find the language scaling, well, now that I am dealing with a more complex program?
> Yes. I've been dealing with a program this complicated for like five or six months so this is nothing new.
At 14:15, responding to another question from chat:
> Do I have my own shader language?
> No, right now we are using OpenGL and [unintelligible] GLSL.
The answer to this third question indicates to me that he is focusing on getting something that works better for him than pre-existing alternatives without getting bogged down too much that every side of his language needs to be perfect right off the bat.
In other words, he is balancing the time to perfect his language against the time he wants to spend making games rather than spending 100% of his time working on the tooling and not getting to write any games.
He made Game Oriented Object Lisp (GOOL) for himself and the other people at Naughty Dog to use when making Crash Bandicoot for the original PlayStation.
He later made another language, Game Oriented Assembly Lisp (GOAL), for the Naughty Dog game Jak and Daxter: The Precursor Legacy for the PS2.
https://en.wikipedia.org/wiki/Game_Oriented_Assembly_Lisp
He has written a series of articles about the making of Crash Bandicoot on his website. Well worth a read!
However Jon Blow's successful games, Braid and the Witness, were not written with that new language.
Until he open sources the code (or at least lets someone else try it/look at it) discussing his “language” is giving him too much credit.
Not sure about “one”, though, Usually you want more than one example before you generalize to a library -> framework -> language.
As one of my professors used to say (a lot):
“Man kann nur von etwas abstrahieren das man verstanden hat”
You can only abstract from something you have understood. And premature abstraction is probably one of our biggest problems.
Interesting, yes. More productive, not sure.
It's basically quality versus quantity, or in the words of Stalin: "quantity has a quality all its own".
So far scaling horizontally (more people working together) seems to fare far better than faring vertically (one or a few people being way more productive alone or in a small group).
I have this itch that there is an explicit slot in our native language infrastructure for a scripting language that is a bit less clunky than Lua, not so huge as Python, and more ClojureScript like than the other embedded lispies out there, that is trivial to embed, has a fantastic interface to C++ and is utterly pragmatic yet elegant.
A small subset of Python would probably do...
I find this applies to most development, once you muddy the distinction between program and language you can see how the concept applies to other things - that is, it's a continuum, and artificially and prematurely locking down the design and implementation of a lower level piece before exploring the landscape can hurt... though determining what is "premature" and what is not is of course pure intuition.
Processing on the other hand is more of a way for visual people to get into programming and do visual representations of data or art. A matter of fact the demo for V / Volt made me think of Processing and finding out that it can be cross platform made me wish Processing would produce native binaries like this that compile down to very small executables whilst still maintaining the same syntax (which is very Java-like, but not entirely necessary to reproduce a full on Java-like language for this purpose).
I totally agree, for certain projects it makes a lot of sense to build your own language. I wish those mainstream engines would stop embedding C# (and I love C#) and make something much more creative. There's the not-so-mainstream engines out there too that do implement their own languages like GameMaker and friends. DarkBasic also comes to mind.
Creating a language is in an orthogonal dimension to the plane that Sapir-Whorf lives on. The realization that you can create and utilize constructed languages, not just the given languages, to solve problems. A computer programming language is a meta-tool, one uses the language to shape and reify ideas. So a computer programmer is a meta-tool user. Someone who creates computer languages is a meta-tool creator. And they are designing an idea that is congruent mathematically, mechanically (can we compute it) and mentally for a human. Maybe my version of the Turing test is, "design me a computer language to represent and solve X"
First, ignore negativity and focus on getting constructive feedback. One of my tiny regrets is that I abandoned one of my projects due partially to negative energy. Many years ago, one of my projects was shared here ( https://news.ycombinator.com/item?id=226480 ), and the feedback was kind of a buzzkill (especially since I wasn't the one sharing it).
Second, think about the growth you want. While I could ignore the buzzkill and keep the faith, I used my language to put a real product out into the world. The crazy thing is that I got it working and working very well, but when it came to hire. It was a cluster fuck. I should have spent a bunch more time on documentation and examples, but I had other concerns that were higher priority. I ultimately had to abandon the whole thing, and I just rewrote everything in C# and used Mono. It was painful, but the company was able to grow faster since the tools were somewhat standard and a plethora examples for the new hires.
When I look back, I was onto something. If I had kept the faith and pushed through, then I would have created something very similar to HHVM which Facebook uses. My strategy back then was to create a less awful language, improve it, then port the platform bits to a better ecosystem and preserve the "business logic".
My core advice with the programming language side of the house is to find a partner for you to lead/follow with shared values. Make it open source as soon as possible, don't wait.
Is this language going to be open-source? It seems incredibly impressive, and 100% overlapping with what I'm trying to do with Zig.
> V compiler is written in V. The language will be open-sourced later in 2019. > Is Volt open-source?
> Not at the moment. Due to several reasons, right now the development model is similar to that of Sublime Text. The app is going to be open-sourced in 2021, so you don't have to worry about it being abandoned.
Edit: Just in case people miss the responses, my apologies, this quote may be referring to Volt the app, not the language (V).> V is compiled directly to x86_64 machine code (ARM support is coming later) with no overhead, so the performance is on par with C.
Which is interesting. There is a lot more information required still but direct may also imply that it's doing the actual instruction scheduling too rather than relying on LLVM. I'm looking forward to hearing more.
I don't see any mention of meta-programming for V, which seems to be a big emphasis for Zig? This seems like a massive feature that at least I'd care about. I haven't personally had the opportunity to try Zig, but I'm routing for you, so I hope you keep going with the project.
I thought it was a new name for Zig seeing your name and the description in the link. ;) It actually looks about too good to be true, especially that it can handle any C++ to V conversion. I was pushing people to check out languages like ZL exactly to rid us of C++ without throwing away legacy code. If it can do that and fast compiles, I can't wait to read the full write-up later on.
Btw, I encourage you to keep at Zig for diversity in systems, language space. Plus, macros. I tell people to avoid them by default for more maintainable code. However, there's times where it's better to have them than not have them. I was happy to see D, Rust, and Julia do macros. Zig and V should have them, too, for max productivity.
To amedvednikov:
1. The name. Although Kesterel had a V language, that was long time ago. You're not stepping on anything. I just encourage you to do one people can spell and pronounce easily that isn't already taken. That will make both search results and adoption a little better.
2. Macros. Like I said above. I saw you mention Go which intentionally tries to keep a standardized language for maintainability and easy compilation. I get that. You could add a warning to the main page that macros are available but discouraged for most situations for those reasons. "Use them only when the cost is worth it." Can just do two passes: one for macros, one for regular code. Your incremental compilation should knock out most of what little slowdown there is.
On the other hand, they should be most of the code if taking a DSL- or MOP-like approach. The people using those will be very familiar with the higher-level language. There's a solid, lower-level language underneath for when the VHLL's don't work out. The macros help there.
Second, unsubstantiated proclamations like "Overuse of them led to LISP code being hard to read" reinforce the previous point. Could you provide a clear reference where Lisp macros are considered "mistakes of history"? Clear references where overuse of Lisp macros turned out to be a problem?
I'm curious if you've ever used a Lisp development environment with facilities such as interactive macroexpanders or if you're just assuming things based on your (incomplete, suspect) understanding of the domain.
Capitalization isn't a deep signal.
There are lIsPs like Clojure that argue (> data functions macros). Although I mostly disagree (for example I love Racket macros), I understand and appreciate the sentiment. I have heard it from other people who have worked with a variety of LiSp code bases over the years. TL;DR: Any form of non-trivial DSL needs supporting materials like documentation and a simple, clear design.
Although it is nice to be able to expand macros, fully-expanded macro-generating macros are clear in approximately the same way as assembly language. It is impressive if you can navigate that, but even more impressive if can manage not to need to do so.
That's not really Lisp related. It's more like how the community likes to see code being written.
For example I would regularly make use of macros to provide more declarative syntax various programming concepts.
There are Lisp dialects which are light on macros and some which are using macros a lot more. For example the base language of Common Lisp already makes use of many macros by providing them to the user as part of the language (from DEFUN, DEFCLASS, ... INCF, upto LOOP).
Actually both versions are valid.
You seem to not know historical information about Lisp/LISP. While Common Lisp is spelled "Lisp" and more modern use is Lisp, historically LISP has been prevalent (and tons of Lisp dialects prefer the capitalized version, e.g. like "fooLISP" or "barLISP").
Second, you are concerned with superficial details people don't and should not care about. We're programmers, we care about the code and what you can do with it, not about whether some language is "properly" spelled in caps of mixed case.
Third, you are rude, which is worse than both of the above.
I learned about it from old books, often on AI, I could scrounge up when I didn't have the Internet or a computer. LISP as in LISt Processor. An acronym. Due to broken memory, I sometimes forget which term to use on stuff that's faded away. I end up about randomly using LISP or Lisp unless its Common Lisp where I usually see "Lisp" in write-ups.
So, good guess.
I don't think that's the case.
That poster your comment goes to claimed that there are types of macros which make debugging harder - not code reading.
Debugging code which makes use of macros is more complicated than code without. There is no doubt about it. One part of it is that debugging happens in a different place -> code transformations with side-effects are running in a compiler or with interpreters at runtime.
One of the main goals is simplicity and maintainability. I want people to be able to jump into any code base (including stdlib and compiler) and understand what's going on. Macros don't help with that.
I went through like 10 names and ALL of them were taken. There are a lot of programming languages out there :)
Have you read my articles about macros and what Zig does instead?
https://andrewkelley.me/post/zig-programming-language-blurs-...
I would be curious to hear your thoughts with this context.
V programming language https://www.vcode.org/
I don’t think that “Basically like C but a tiny bit better” deserves to be associated with the word “diversity”.
FTR, I found his (former?) eul\.im which now redirects to some fishy website.
V looks interesting, but I'll wait and see before I jump onboard.
Lots of handwaving, things mentioned as language features on the webpage and then revealed to not be present (in responses), and lack of specifics...
* Strong modular system and built in testing.
* Global state is not allowed.
* There's no null and everything is automatically initialized to empty values. No more null reference crashes.
* Variables are immutable by default and functions are partially pure: function arguments are always immutable, only method's receiver can be changed.
* Thread safety and guaranteed absence of data races. You no longer have to constantly ask yourself: "Is this thread safe?" Everything is! No perfomance costs either. For example, if you are using a hash map in a concurrent function, a thread safe hash map is used automatically. Otherwise a faster single thread hash map is used.
* Strict automatic code formatting. It goes further than gofmt and even has a set of rules for empty lines to ensure truly one coding style.
Especially eye catching is the 2 mode of every data structure. Switch to thread-safe if there are concurrent access.
I'm not a fan of null (option types seem better -- which V does say it has), but defaulting to an "empty" value isn't the answer IMHO as it makes it much harder to debug by obscuring that there's a problem at all. You may not realise that the 0 is actually an "empty" and not a valid 0 until you realise all of your calculations are wrong, months later.
Adding any keyword is by definition breaking backwards compatibility, so I'd say this is the correct behavior.
For example, "goto" is a reserved word in Java, while not a keyword. Inversely, in Fortran, keywords are not reserved names, so `if if then then else else` is valid. C# has "keywords" and "contextual keywords", both categories being keywords, but only the former being reserved names.
Regardless, a builtin might be referring to a function that's included as part of the base language - like make() in Golang or zip() in Python.
EDIT: Since someone has gone through the trouble of downvoting this viewpoint, I would like an explanation as to why I'm wrong here. I cannot imagine a scenario in which doing so would not likely break existing code.
I think I must be misreading you, because it sounds like you're arguing for the idea that adding new names to an API should be considered a breaking change? I'll accept that maybe reflection will catch those changes, but with that exception why would any code even notice?
I already have a "filter" function defined in my program, so it will shadow the builtin function, and my program will still work as intended.
Those are exactly the ideas I had for what would make a perfect language! (Assuming they're implemented properly of course).
Simple features. Immutable and pure by default (but not dogmatically so). Fast compile. Hot reload. Automatic C interop. Fast-ish. Built in niceties like hashmaps, strings, and vectors (niceties compared to bare C). Receivers so you don't have to do the song and dance you do in C to tie structs and functions. No header files!
Go came close, but no cigar. Rust added the whole kitchen sink and loads of accidental complexity. Anxious to see how this fares...
https://web.archive.org/web/20180615121501/https://volt.ws/
https://web.archive.org/web/20181023093131/https://volt.ws/
It would be great if the roadmap contained realistic items. Once a user is burned by an unmet expectation he won't believe anything else on the website.
I made lots of mistakes that caused the delay, I'll post a detailed blog about it.
Should have sticked to "it's ready when it's ready".
Ironically this time it it really is going to be released tomorrow (Feb 7).
The entire Spring framework is IMO an elaborate construction built so that engineers could use global variables without their managers finding out. There is little to no difference between carefully using global variables and Spring dependency injection except syntax.
The best solution I have ever seen to global variables is definitely parameterize with Racket (https://docs.racket-lang.org/guide/parameterize.html). I don't think Racket was the first language to come up with this, but it was the first one I am aware of. The basic idea is that you define some global with a default value. However, you can call parameterize to change the value for the duration of some input function. It is made thread safe by using thread local memory. It then resets the parameter back to the default value at the end of the function.
On the other end of the spectrum, I think Rust also has a very good implementation of globals. It will let you use global variables, but you have to declare it as mutable, use some form of locking, or use an UnsafeCell. Additionally, you have to mark your code as unsafe any time you try to read or change this global variable.
Until you need to write unit tests.
Isn't that basically Perl's `local`?
https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynam...
Racket's parameters are just dynamically scoped variables. Most Lisps have them. The older Lisps actually predate lexically scoped variables and had dynamically scoped variables exclusively! Emacs Lisp is not even that old and only had dynamic scope until relatively recently.
In Scheme it is common to see `fluid-let` to handle classic dynamically scoped variables.
const red = gx.Color{255, 0, 0}
or even call simple functions that only return values
const red = gx.rgb(255, 0, 0)
A lot of people continually tinker with mental models that are into the Gigabyte-equivalent range in terms of all they intend and promise to do. One example here on HN might be the "startup" model. What "it" is seems pretty fluid at this point and in various discussions it gets mashed and molded to fit this concern or that one. Better models will come along that will solve problems nobody can yet put their finger on. (I'm speaking in the abstract here, but I've experienced and worked heavily on this kind of model-change and it can be very valuable.)
What typically happens is, someone comes along and isolates an issue which promises high leverage or high controversy or both, brings a set of problems into really sharp relief and remains in the needed context without the burden of supporting and interlinking with every other context out there, and voila--a powerful solution emerges in a very efficient way. Pretty soon everybody who needed a [startup] mindset now needs a [successor-lens] mindset. And not just in name--it's clear that this can really help. It's good stuff.
It's really just more of what we call "technology" and is observable in the same sorts of curves, but again, there's a model that's overburdened--the technology of the mind still overlaps with and rubs against what we consider "true" technology of the "useful arts" sort. As a civilization we suffer, mostly unknowingly, under the burden of yesterday's thinking about how things fit or don't fit into which categories.
This is "the deal"...
There are many computer environments beyond the desktop and cloud servers. Arguably most computer environments.
But to reduce it: imagine an O&G pipeline controller that stupidly did something bigger than QNX & C. That will be pumping oil and gas for 30 years. Online upgrades, until some young turk blows out the library size. Oil spill with a blown line, and New Jersey explodes.
Now that I have experience with translating C/C++, it would be really cool to translate existing Android Java apps to V. This would talk more than a year probably...
It does seem similar to Nim and Zig, I just think Rust is in a different category from almost all other languages all together.
I haven't had any problems with build times thus far, how big is your project?
Of course I didn't need a new language to make my project compile faster :) I just wanted a simpler C, and I had some experience with writing languages (I wrote 2 languages at school/uni).
Now I'm actually more excited about V than the original product I created it for :)
First, nice concept, but without open code, it might as well not exist, and without open specification, it might as well be yours alone, like one of Tolkien's languages. Closed languages wither and die, and yours seems well onto that path.
Second, what makes V compelling to you appears to be completely uninteresting to me in terms of language design. It might as well compile from V to Go; I can't see why not!
Whenever a language designer appeals to simplicity, they are usually appealing to whatever makes it possible for them to be productive, and they are usually missing that the productivity is personal because the designer is the one who builds the language. The GL demo seems to be a great example of this sort of situation.
I hope that you publish your work so that we may properly critique it.
Edit: Here is another language designer who is not me saying "closed languages die" (https://blog.golang.org/open-source). I think that, until we actually have a compiler for V (or whatever it is hopefully renamed to before release) in our hands, we ought to be extremely careful about trusting that any of this exists. It is all too common in PLT/PLD for somebody to come in with bold claims, outrageous mockups, and zero toolchain. I addressed what I saw, which is yet another compiles-to-Go hobby language. To become more than that requires a committed community and a common repository of open code, and the author appears to have only the former.
I don't know about this author, but for me, this would emphatically not be a motivating reason to publish my work. I might publish work so that someone could get some use out of it, or to show off my brilliance. But if all you're going to do is critique it (no doubt with all the familiarity born of five minutes of looking at the tutorial), then I'd just as soon you never see it.
>Here is another language designer who is not me saying "closed languages die" (https://blog.golang.org/open-source).
I don't think the person you're quoting would advocate that languages must start out as open source. Go sure didn't. It was developed closed source within Google for two years before it was even announced.
If they were an arrogant shit-head then I'd probably just block them, regardless of the technical merit of what they wrote.
plus this may just be me as a non (designing a tool language for a project) dunce speaking but reading a critique of a language/framework that i haven't thought of makes me want to try out the language and see how that shortcoming affects the way i work. it's the reason i tried out Go and Elm and Vue.js
Basically you're right if the creator wants a widely-adopted general-purpose language. But there's other valid approaches I think.
This is unnecessary harsh. The author has already said it will be open sourced later. I can understand the reasons to not open source now. Managing an open source project is no small work.
Second, notwithstanding V's slim feature set, it's already more successful than 99% of language design attempts out there in that it ships. It certainly succeeds in letting the author to build his other projects faster and easier. It fulfills the author's own needs. I'm sure Perl and Python started that way.
This. It's crazy to me how quickly developers are ready to get behind something without even being able to use it. Jai is similar in this regard.
It's easy to make wild claims like "super fast compilation" or "can be translated from C++" when you don't have hundreds of users, all finding edge cases and wanting different things. Especially easy when you haven't released anything so everybody is projecting their favourite features onto the language.
Having all my library in the same language make a lot thing like debugging and testing easier. It also semplify the mental model i have of the program.
Also C(lang) interop is my main struggle with go. For me it is such a pain that something i wrap a c library in a stdout/stdin server and just spawn it and use cap'n'proto for communication. When you use cgo you lose the easy cross-compiling, i would love for something similar in go and/or rust.
I wonder if llvm could be used to implement a sort of universal transpiler. even if it not use the target language in a semantic language it still make a lot of thing easier.
Yes, I'm super excited about it!
I couldn't save settings, and from then it kept on crashing after restarting the app.
I'm always curious when people complain about binary sizes. Was there some reason the binary needed to be small? Or just based on some sense of 'largeness' and 'smallness'. It seems to me like rewriting in a 'less productive language' to save a few mbs of binary size that nobody cared about anyway is a pretty big waste of time.
I don't mean to come across super critical, there are cases where binary size could be really important. Say you're on an embedded platform with minimal memory. I just don't /understand why it was something worth optimising over here... especially to the point of a rewrite
All of the download links just give todays date and issues in the GitHub page the site links to mention it being flagged by virus or not being supported.
It should be instant. But when I was making this gif, there was some kind of a bug, and I some how made it work only after it reaches the edge.
I was not able to reproduce this :)
I'll make a better gif once the new website is up.
I hope it succeeds and is released soon! Thank you very much for your work.
Is this saying you can actually get compile time improvements compared to the original codebase? If so I can imagine a couple of ways this could work-
1) skipping the optimization the C/C++ compilers would do, with V's direct-to-machine-code generator, and/or
2) doing some heavy lifting in the translator, so the equivalent V has more redundancy and less implicit information.
How close am I? Or is there something else here?
This is quite a controversial statement. But it could indeed be true, see this article: [1]
[1] https://softwareengineering.stackexchange.com/questions/2037...
It gets hard the more features you add to have a consistent experience and all the other tooling a language has (like debugging).
I find these problems fun and help in making you a better programmer, but the cost to be successful is immense.
It's an excellent book and is incredibly approachable.
From what I know C++ is an extremely complex language. How do you deal with the complexity? (Especially considering V is meant to be simple)
I'll post a detailed article about it soon.
How does the resulting V code look like for non-trivial templated code, say something you'd find in one of the more complex Boost libraries?
(BTW, the language itself is exciting!)
Does V encourage one or the other? (coming from a C background, I prefer underscore_case)
Does V have Go's funny "uppercase export" rule? Only identifiers that start with an uppercase letter are exported from a module?
It doesn't have the uppercase export rule.
It's going to be either Rust's `pub` or Oberon's `*` or `+`, haven't decided yet.
How do you plan to translate the latest C++ standard with all those template stuff?
Few ideas I had:
- Simple classes (no inheritance, only mixins) like in JavaScript
- Always pass objects by reference as in Java to avoid the pointer mess
- Copy the core APIs from ECMAScript
I'd love to see how V generates its machine code. Using the Go syntax is a wonderful idea.
What are traditional compiler makers missing?
Link refers to the same page.
Edit: I see now. It's just a chat app with a bunch of protocols and a clean interface.