Comments (122)
Hi @medvednikov !
My answer will be off-topic: I just wanted to thank you for what you are doing with Volt and V, both look very promising !
I see a huge amount of feature requests, and I just wanted to say: Take your time, good softwares takes time. It's easy to get overwhelmed building Free softwares: sometimes it's better to say "no" or "not for now" in order to build great things in the long run :)
Have a good day !
from v.
Just curious, why not go the other way with strings, and only use double quotes?
That seems more cross language consistent as it means you get variable interpolation etc., and in my experience apostrophes are much more common in strong literals than double quotes, so if you’re going to pick one the double quotes will require less escaping.
from v.
Here's an assortment of thoughts:
From a Ruby and C background, I quite appreciate constants having to be uppercase. It also helps grepability (you know that you have to grep 'const CONSTANT_HERE' -r *
if you want to find the value of a constant).
You may already want to put special thought into the HTTP library since I assume it will see a lot of usage. In particular, you may want to support both synchronous and asynchronous patterns; consider some standard library way to event loop all kinds of networking.
I enjoy the design of the or
keyword and how you can immediately force a return. However, I'm not sure if an implicit $err is always the right solution. I'm worried about localization and internationalization of error messages in particular.
How do you return failure from main? This isn't as much of a concern on Windows and for GUI applications, but your example doesn't seem to address a case like int main(void){return EXIT_FAILURE;}
in C. I'm also rather happy about eprintln()
existing; you may, however, want to look at the BSD err(3) family, which print a message to stderr and then exit with the given exit status.
I'm not sold on having both '
and "
as string delimiters with no semantic change. I know that Python does that, but considering UNIX Shell, Perl and Ruby all consider '
to be special in prohibiting variable expansion, you might want to do the same.
Looking at the printing examples: Is it accurate that a variable identifier can be any character.
What happens if you try to println()
an array type? My intuition would suggest that a compilation error would have the least surprise, but you may want to do something else.
What even is an int
? Is that a literal C int
with all the risks of undefined behavior on signed overflow? Are unsigned types even available? Sun's experience with Spring (the OS from the 90s, not today's Java framework) showed that you kind of need unsigned integers for writing device drivers.
Are you making any guarantees about the C code output of a function that only does arithmetic on integer types and has no branching? This may be relevant for the implementation of cryptographic algorithms in particular.
Concurrency remains an open issue to address in another example, too, probably.
from v.
Hi @loic-sharma
One of the main philosophies of V is to make code readable, maintainable, and predictable.
One of the requirements for this is having only one way of doing things. Every single feature of the language has only one right way. The exception right now is string literals (see the '
vs "
discussion).
If uniform function call syntax is implemented, every single function can be called in two ways. This is unacceptable, sorry.
V is a very strict language, and the one way only rule is going to make about half of programmers not happy by definition. C++, Nim, Rust, Scala etc are languages that support lots of paradigms and give developers lots of freedom. As the result, the complexity increases, code can get hard to understand, maintainability suffers.
Go has a similar philosophy. And I remember lots of people not happy about being forced to place {
on the same line and using tabs instead of spaces. But in the end I think most will agree that it was the right decision that saved a lot of time (no more arguments on code styles and on which paradigm to use) and made code simpler.
What's wrong with fn (r Repo) find_by_id(id int)
? fn (user User) is_bob()
can also be chained.
from v.
@slimsag @boyter I'll add an example with Generics soon.
@rrjanbiah yes, but coroutines and channels have to be implemented first.
from v.
I myself find u16
much more readable than uint16
.
I think one of the unwritten rules of V is the fewer unnecessary keystrokes, the better. But within reason! (looking at you, Perl)
That's why there's no :
between names and types, no ->
before return types, no ,
in struct initializations, etc.
from v.
Are things like
if
s and blocks expressions?
I think it's very important for languages with immutability by default to have if expressions:
a := if condition { value1 } else { value2 }
vs
mut a := 0
if condition {
a = value1
} else {
a = value2
}
from v.
from v.
@scurest not right now, but they will be.
from v.
from v.
Hi @xorhash
Thanks a lot for your detailed feedback!
You may already want to put special thought into the HTTP library since I assume it will see a lot of usage.
Absolutely!
How do you return failure from main?
Just like in go: os.exit(1)
However, I'm not sure if an implicit $err is always the right solution. I'm worried about localization and internationalization of error messages in particular.
err
value is set with return error(error_msg)
. Error message can be fetched via gettext for example.
Looking at the printing examples: Is it accurate that a variable identifier can be any character.
Can you explain what you mean?
What happens if you try to
println()
an array type? My intuition would suggest that a compilation error would have the least surprise, but you may want to do something else.
println
supports everything that has a str()
method. Arrays have that predefined.
So println([1,2,3])
will print [1, 2, 3]
:)
What even is an
int
? Is that a literal Cint
with all the risks of undefined behavior on signed overflow? Are unsigned types even available?
Very good question. This will be one of the first topics in the docs. V has byte
, i16
, int
, i64
, u64
etc.
int
is not like in Go or C. It's always an i32
. I just personally prefer int
to i32
. It's used in approximately 80% of cases in Go stdlib, so I made an exception for it. It goes against the philosophy of the language, but I really like having int
instead of i32
.
Are you making any guarantees about the C code output of a function that only does arithmetic on integer types and has no branching?
Could you please give an example?
Thanks
from v.
Also, off topic, but since the above is my first post on your project I just wanted to say hello! V looks fantastic, take the good stuff of Go and make it even better (to me anyway).
Would love to help if there’s any way I can. Please let me know :)
from v.
Hey @citycide
Thanks for your feedback!
Is this a typo in the generic example?
Yes, I initially called it retrieve
:) Fixed.
Do you always have to
return
from the outer function? How do you just do default values, or equivalents for some of Rust'sOption
methods?
Can you write a small example?
Is there any short lambda syntax?
(a, b) => a + b
Not yet. Most likely there will be one. Need to think about the details.
How about pattern matching? It's one of my favorite features in Rust and ML languages, especially F#.
Same :)
from v.
- No, it will be exactly like Go. Structs, embedding, interfaces.
- Yes. Again, same as Go.
- Yes.
- No.
- Right now you can call any C function:
C.puts('hello world!')
from v.
The documentation tipped me off to it, but why does const API_URL = 'https://vlang.io/users.json'
use =
rather than :=
?
It also seems weird to name a while
loop for
. Maybe just call it loop
since the condition is optional?
from v.
@xorhash simplicity and consistency with other languages.
Having only one keyword instead of three (for
, while
, loop
) helps keep the language smaller and simpler.
:=
is used for variable declaration, const
is for consts.
from v.
Do you plan to introduce constructors in V? My biggest issue with go is the lack of constructors due to default empty values for everything. It’s effectively impossible to prevent instantiation with invalid state.
from v.
@medvednikov, building on the example @oliwer gave, one can always do t := Thing{}
and bypass constructor validation.
from v.
In rust it’ll work in the same module, but not from outside. Uninitialized fields + private access works fine to protect against invalid state.
Of course, your own module can create invalid state, but the point is preventing users of your library to do it.
from v.
from v.
Options are not error handling! Or at least not only, though some errors can be modeled with them.
Error handling should surely be strongly integrated into the language, (thus why I asked my first question to you about if errors will be extended past strings!), but I don't think that the option type should be conflated with that. They do share some similarities (e.g. you may want to be able to chain computations without handling every step in between), but are also quite different (e.g. you will often want to be able to coalesce different error types together for easier handling).
Maybe it might make more sense to talk a little more holistically about what your plans are for the error handling system? It could make the conversation a bit more concrete.
from v.
As for '
, I want to have only one main way of denoting strings. V will automatically replace "
with '
if there are no apostrophes in it.
I might remove "
entirely and force developers to just escape apostrophes.
'
strings can have $vars and newlines, unlike all other languages, yes.
from v.
@International no.
V compiler used to rely on generics to implement arrays and maps, but then I replaced them and made the code smarter (similar to Go's slices and maps).
There will be a way for users to create their own generic containers without generating extra code for each type and slowing down compilation time.
from v.
I've added an example with generics:
https://github.com/vlang-io/V/blob/master/examples/generic_repository.v
from v.
I think it looks pretty good. I like a lot of the semantic choices you've made even if I don't particularly like some of Go's syntax that you're inheriting. I'm sure I'd get used to it though (except []User
vs User[]
that'll drive me insane 😆).
Immutability and first-class optionals (T?
) with those nifty or
blocks are great. I'm not sure I fully understand the way the or
block works though. Do you always have to return
from the outer function? How do you just do default values, or equivalents for some of Rust's Option
methods?
It's going to be either
pub
or some symbol like in Oberon.
Either of these is good IMO, I don't like Go's capitalization rule for exports.
Backticks are used for characters. Which feels a bit weird.
It's probably best to use double quotes for strings and single quotes for characters but I understand the ease of typing isn't great for you. I use single quotes in JavaScript/TypeScript all the time but with everything else I code in using doubles, it can be a bit of a context switch.
Is there any short lambda syntax? (a, b) => a + b
How about pattern matching? It's one of my favorite features in Rust and ML languages, especially F#.
Is this a typo in the generic example? Should retrieve
be find_by_id
here:
from v.
@Francesco149 this is a discussion about the syntax of the language.
V can compile to machine code directly, as well as to C.
from v.
I know, that's different. But due to the design and philosophy of the language, it's a necessity.
from v.
@Tim-St V is being designed also for game development and science. Since conversions have to be implicit, there will be lots of float64(
in the code. I think it's too verbose.
As for the function keyword, let's put it to vote:
https://twitter.com/vlang_io/status/1099687714042114049
:)
from v.
@burlesona what you described is nice and works well in a language like Ruby.
V has a very different philosophy. Everything is transparent and straightforward. If a function is called, it should be clear.
Since there are no constructors, would you automatically call these validators on every .age = ...
and {age:...
? :)
This reminds me of notorious C# properties where a simple user.Name
could call an unlimited amount of functions and it would never be visible to the caller.
from v.
Sorry, I left this thought out of my write up:
I think it would be reasonable for every struct to have a ‘new’ function, and that it’s a no-op by default, but can be explicitly defined to put initialization behavior in if needed.
However I agree with you about the strictness and explicitness you’re going for. I think a declarative set of constraints on the properties of a struct is a nice way to handle this concern, that way there’s one and only one way that a property can have behavior, that’s using the constraints on the declaration.
Hope that makes sense.
from v.
Or I could just do what Rust does and not allow constructing using field names if there's at least one private field :)
In any case, it's a very important feature, and it will be implemented. Thanks for mentioning this @andrenth
from v.
No protection of fields and package variables was one of my biggest gripes with Go.
The fact that it's possible to do stuff like this os.Args = append(os.Args, "lol")
is ridiculous.
from v.
Are things like if
s and blocks expressions?
from v.
@PavelVozenilek your second variant already works in V. It's just like in Go.
@jkaye2012 you can do for num in numbers
, I decided to leave the C-style loop as a safer alternative to while
.
from v.
I never said options are error handling only. In V option == Rusts's Result + Option. So maybe I should just chose a better name.
You can return error strings (return error('foo')
) or error values (return os.NOT_FOUND
).
from v.
Or did you mean what happens if we call print([]User)
? Compilation error :)
from v.
Will you keep raw string literals (backticks) from Go?
from v.
@burlesona JSON is very popular right now, and it has lots of "
.
Also to me '
's look cleaner in the code and don't require shift.
But I had your exact thoughts, maybe I'll do that. Just to be consistent with other languages.
@slimsag '
behaves exactly like ` in Go.
from v.
@medvednikov yeah it’s kind of tricky to balance, I think this is why most languages have a few string literal options :)
Maybe a block string literal syntax like Ruby’s heredoc (or many other examples) is a viable alternative for things like JSON input? But it does result in more than one way to make a string, which I agree isn’t perfect.
Or finally, less easy to type, but you could just go straight for backticks or some other universal string delimiter.
from v.
@medvednikov Not true -- '
is a rune literal in Go and cannot contain multiple characters nor newlines and supports escape codes, in contrast ` is a raw string literal supporting multiple characters and newlines with no support for escape codes
- Example: https://play.golang.org/p/6iVhZAWMU9n
- https://golang.org/ref/spec#String_literals
- https://golang.org/ref/spec#Rune_literals
from v.
Hello @medvednikov and congratulations for V! It seems to solve many of Go's issues and could be a nice "better C". A few questions:
- since your functions are all lowercase, how do you differentiate between local and exported functions?
- can you tell us more about the what the runtime will do and how do you handle memory management compared to Go?
- how do you declare a character/rune if
'
is for strings? I understand that typing"
is impractical with your keyboard, but you're a minority. Best thing you could do is switch'
and"
, but I guess most people would hate it. - the error handling handling looks great! I also wanted to use
or
as that's what we often use in perl. - will V handle generics?
from v.
Hi @oliwer
since your functions are all lowercase, how do you differentiate between local and exported functions?
It's going to be either pub
or some symbol like in Oberon.
- can you tell us more about the what the runtime will do and how do you handle memory management compared to Go?
There's no runtime, memory management will be similar to Rust.
- how do you declare a character/rune if
'
is for strings? I understand that typing"
is impractical with your keyboard, but you're a minority. Best thing you could do is switch'
and"
, but I guess most people would hate it.
Backticks are used for characters. Which feels a bit weird.
Are there keyboard layouts that don't require shift to write "
?
- the error handling handling looks great! I also wanted to use
or
as that's what we often use in perl.
Thanks! I did some Perl in the past, that might have influenced the syntax :)
will V handle generics?
It already does.
from v.
Would be cool to see an example of generics somewhere!
from v.
+1 to seeing some example of generics.
from v.
OT: Will it be possible to convert Go code to V?
from v.
Hi @medvednikov , does volt also use generics in it's codebase? Does it affect the compile times much?
from v.
I'm very skeptical about the "400 KB compiler with zero dependencies" part. It just transpiles to C and then compiles with gcc/clang, doesn't it? that implies a dependency on gcc or clang. can the V compiler emit machine code by itself?
from v.
Saw a couple of user examples that you published. V Looks interesting.
Since I could not get enough information from the user examples, here are some basic questions that come to my mind.
- Does V (plan to) support OOP, inheritance, polymorphism etc?
- Parallelism?
- Systems Programming, as in support for pointers etc.
- Garbage collection?
I would be glad if you can point me to some documentation.
from v.
Also ABI compatibility with C/C++. Is it possible to link in C/C++ functions directly in V?
from v.
As someone who spends 98% of his time in C & C++ and has no experience with Go, any sort of "V for C Programmers" documentation would be very helpful. 😄 Looking forward to seeing V's release!
from v.
@awesomekyle V is language that can be learned in an hour.
A documentation/tutorial page will be out soon, and you'll see ;)
from v.
users.v says "V will automatically format and align your code." Does this mean the compiler changes the source files by formatting them?
from v.
Looking at the printing examples: Is it accurate that a variable identifier can be any character.
Can you explain what you mean?
Sorry for the late response. I'd sent the message without finishing my thougts there. Is it accurate that a variable identifier can be any character that is printable and not $
or .
? What is the source code file encoding (or is it always based on system locale)?
Are you making any guarantees about the C code output of a function that only does arithmetic on integer types and has no branching?
Could you please give an example?
Assume you have a section of code like this:
// a through d are mutable u32
a *= b;
c *= d;
b += c;
d += a;
// ...more operations...
Do you make any guarantees that the exact equivalent C code is output? That might be useful for cryptography, though it's already hard enough to write cryptographic algorithms in C in a way that your compiler doesn't sabotage you.
from v.
users.v says "V will automatically format and align your code." Does this mean the compiler changes the source files by formatting them?
yes
Is it accurate that a variable identifier can be any character that is printable and not
$
or.
?
No, letters, numbers, and underscore only.
What is the source code file encoding (or is it always based on system locale)?
UTF-8
Do you make any guarantees that the exact equivalent C code is output?
You mean, will the resulting C code be the same? Right now, yes.
from v.
users.v says "V will automatically format and align your code." Does this mean the compiler changes the source files by formatting them?
yes
Linting code tends in general to be done by an external tool; and IDE, a CLI tool, etc...
It could be beneficial for the V compiler to avoid doing task that it do not needs to do :)
from v.
OT: Perhaps all OT should be in https://groups.google.com/forum/m/#!forum/vlang
from v.
V is looking great, I can't wait to play around with the language when it's released! :)
I don't have a background in Go, so this syntax feels strange to me:
fn (r Repo) find_by_id(id int) T? {
...
}
What're your thoughts on Uniform Function Call Syntax? Something like:
fn find_by_id(r Repo, id int) T? {
...
}
// Can be called two ways:
users_repo := new_repo<User>(db)
find_by_id(users_repo, 1) // No syntactic sugar
users_repo.find_by_id(1) // With Uniform Function Call syntactic sugar
This is great for method chaining too:
fn is_bob(user User) bool {
return user.name == 'bob'
}
if users_repo.find_by_id(1).is_bob() {
println('Hello Bob')
}
from v.
That's a fair response. There's nothing wrong with the existing syntax, it's just different for people that aren't used to Go. I'm sure we can get used to it 😄
from v.
Just published the first draft of the documentation. So far it covers the basics.
https://vlang.io/docs
from v.
@oliwer updated, thanks.
from v.
The language looks very promising!
In my opinion code is easier to read when the types are named int
, intX
, uint
, uintX
, float32
, float64
and fn
is named func
(like in Go). And also the string syntax should be the same like in Go (in my opinion).
from v.
@andrenth can you please post a simple example of instantiation with invalid state? Thanks.
from v.
My biggest issue with go is the lack of constructors
But you can already write constructors in Go (and I assume it's the same for V):
func NewThing(a, b string) *Thing {
return &Thing{a: a, b: b, c: "default"}
}
from v.
Indeed, constructors are basically functions. Why complicate the language and introduce another construct.
Just like Go and Rust, V is not an OOP language. It has structs and powerful interfaces, that's it.
from v.
But in rust it works fine because you can’t directly instantiate a struct with private fields except via a function. In go you can bypass the function because everything has a default value.
I’m not asking for the language to be more complicated, just for a way to ensure the function(s) that build an object must be called.
from v.
@andrenth ok I see your point. I'll think about it.
from v.
In Go:
type User struct {
name string
}
func NewUser(name string) (*User, error) {
if name == “” {
return nil, InvalidUserErr
}
return User{name}, nil
}
// But one can do and create invalid state.
u := User{}
I think the core issue is “uninitialized fields/variables should be a compile time error instead of automatically initialized with an empty value”.
from v.
Indeed, in Rust this won't compile:
struct Foo {
a: u8,
b: u32,
c: bool,
}
let foo = Foo { a: 0, c: false };
missing field `b` in initializer of `Foo`
By the way, you wrote that
you can’t directly instantiate a struct with private fields except via a function
But this is perfectly legal:
let foo = Foo { a: 0, b: 1, c: false };
Making uninitialized fields illegal won't really help since it won't prevent instantiation with invalid state:
u := User{""}
can still be invalid.
This is an interesting problem.
from v.
@medvednikov I have some thoughts on the initialization problem.
I know you're not looking to build an OOP oriented language, but in practice every language that has "objects" or "structs" in it faces some of the basic OOP issues. I've worked in Ruby for a long time, and it has some nice, elegant handling for many of these cases.
In Ruby you always make an object by calling the new
method on the class. The class then calls the initialize
method on the object. These both exist by default with no arguments required, and you never have to define them, thus for any class you always just call MyType.new
to create an object.
However you can hook into these methods and modify them however you want, and since this is the only way that an object can be created, it gives you great control over how things get initialized. Now I'll ignore the "class" side of this since you don't want to go for OOP, but here's an example of what you could do at the instance level.
In the simplest case you just define required arguments by listing them in the initialize method, and provide default values if you want.
class Person
def initialize(first_name:, last_name:, age:, team: Team.default)
@first_name = first_name # this assigns the local variable to an instance variable
@last_name = last_name
@age = age
@team = team
end
end
p = Person.new(first_name: 'Example', last_name: 'Person', age: 32)
p.age #=> 32
p.team #=> returns the default team
That's not very interesting, but inside that method it's just code, you can do whatever you want to validate the arguments, ie.
class Person
def initialize(first_name:, last_name:, age:, team: Team.default)
@first_name = first_name.to_s # ruby is dynamically typed but you can coerce like this
@last_name = last_name.to_s
@age = age.to_i
@team = team
raise ArgumentError, 'First name must be at least 1 character' if @first_name.length < 1
raise ArgumentError, 'Last name must be at least 3 characters' if @last_name.length < 3
raise ArgumentError, 'Age must be positive' if @age < 0
end
end
That works well but it's a little verbose, so a common pattern in ruby is to define macros to automate assignment and validation of initialization arguments. Skipping the implementation details, the result looks like this:
class Person
argument :first_name, String, constraint: -> s { s.length > 0 }
argument :last_name, String, constraint: -> s { s.length > 2 }
argument :age, Integer, constraint: -> i { i > 0 }
argument :team, Team, optional: true, default: -> { Team.default }
end
The idea here is that you list arguments, their type, and then you can set some options like whether a value is optional, and anonymous functions to validate the input or provide the default value.
Extending that kind of extended type definition seems like it could be a nice solution for V. I could see a very similar syntax working nicely, for example:
struct Person {
first_name: string, constraint: -> s { s.length > 0 }
last_name: string, constraint: -> s { s.length > 2 }
age: int, constraint: -> i { i > 0 }
team: Team, optional: true, default: -> { Team.default() }
}
Now you've got a straightforward, declarative definition of how a struct gets created that should handle the issues in the discussion above. Even better you can
No worries if that's not your cup of tea, just thought I'd throw that out there for you to consider :)
from v.
Would read-only struct fields solve this problem?
user.name
can be accessed, but user.name = ""
or User{name:""}
would result in a compilation error.
from v.
Or I guess you could call them only when the struct initialization syntax is used.
from v.
To reply more specifically to “should these be called on every .age=“
I would say yes, but keeping in mind that your ability to declare constraints is pretty limited (in a good way).
But let’s explore what you’ll need if you don’t do that.
Can you define custom types with some constraint behavior? If so, simply making an Age or FirstName type with the relevant constraints would have the same effect.
But since v has no nil, what do you do if a struct is created and some properties are undefined?
from v.
But since v has no nil, what do you do if a struct is created and some properties are undefined?
They are initialized to zero values (0 for int, "" for string, Foo{} for struct)
I suggested read-only struct fields. Maybe even by default. They solve this problem.
from v.
Yeah I agree properties being read only is a nice way to handle that. I will say though it might be nice to have a shorthand for “copy and change,” for cases where you have a lot of properties and need to make a new object with some changes.
from v.
from v.
I don’t see how read-only fields solve the invalid state problem if they’re initialized to zero values, but maybe I didn’t understand the proposal.
from v.
@andrenth getting rid of automatic initialization won't solve the problem because people still can do things like u := User{name:""}
and not initialize the object correctly.
Besides, it's a key feature of the language, lots of functionality relies on it. For example, Config structs which are used as a replacement for named arguments.
Making all fields in User
read-only would make the example above not compile. However it would still be possible to do u := User{}
.
Y could make User
unexported, but leave its fields exported. It actually works in Go:
type user struct {
Age int
}
func NewUser() user {
return user{10}
}
u := foo.NewUser()
fmt.Println(u.Age) // 10
u2 := foo.user{} // cannot refer to unexported name foo.user
There's a big problem with this approach though: now it's impossible to reference foo.User. We can't have foo.User arguments or struct fields.
So the only solution I can think of is to add a flag that doesn't allow a struct to be manually initialized.
from v.
Or I could make it super strict: if there's at least one read-only field, manual initialization is not allowed, since technically User{}
is the same as User{name:""}
. But name
is read-only and cannot be set from an outside module.
from v.
Just added an example with some concurrency and mandatory locking:
https://github.com/vlang-io/V/blob/master/examples/concurrent_news_fetcher.v
from v.
Could you explain the func main() {
and go fn() {
?
Have you yet settled on a keyword for functions and just not updated it everywhere?
from v.
from v.
from v.
Interesting! Does that mean all access to variables defined outside the current thread must protected by a lock?
from v.
@oliwer yes, as long as they are mutable of course.
from v.
Cool, thanks!
In the example code on the language comparison page, the V example contains
for cursor < ids.len {
lock { // Without this lock block the program will not compile
id := ids[cursor]
cursor++
}
...
If another thread has incremented cursor
between the check in the for loop and taking the lock, the subscript ids[cursor]
might be out-of-bounds. Can this happen?
I also wrote a simpler Rust implementation.
from v.
@scurest thanks, I'll update both examples.
from v.
@scurest you implementation uses crossbeam, which is not part of Rust. The implementation I posted also uses 3rd party libs (it depends on hyper and rustc_serialize).
I understand Rust's philosophy of promoting use of 3rd party packages,
but after giving it a thought I realized that it's more fair to Go and V to only use the tools the language provides.
But is it even possible with Rust? It looks like even JSON serialization is not part of stdlib.
You can run the V and Go examples just by downloading the source and building it.
Rust version (including the one I originally posted) requires installation of 3rd party packages.
P.S. I'm clearly not a Rust dev ;)
from v.
from v.
From the docs:
if ... the braces are always required
This would make chain of ifs awkward:
if a {
} else {
if b {
} else {
if c {
} else {
}
}
}
If expressions would feel even worse.
This could be fixed in two ways:
- Adding
elif
keyword (preferred by me). - Adding exception to "always braces" rule.
Variant [1] would look like:
if a {
} elif b {
} elif c {
} else {
}
Variant [2] would look like:
if a {
} else if b {
} else if c {
} else {
}
from v.
Manual index management in for loops feels like an eternal source of bugs that has existed forever. Why not use iterators/ranges instead? Or maybe this exists but it's just not documented yet? Given the auto-enumeration that's documented, I'm not sure that the c-style loop is ever really required? I do like that there is only a single looping construct though.
from v.
@medvednikov: One more thing. It will be tempting to use if expression to isolate initialization code, like:
a := if true {
mut this := ...
mut that := ...
... // lot of calculations
42;
}
For such situations just a block could be used:
a := {
mut this := ...
mut that := ...
... // lot of calculations
42;
}
from v.
Hi,
First of all thank you for what you're doing, I can't wait for V to be open-sourced !
Concerning the " vs ' debate, one argument for using " to delimit strings is the fact that some languages make use of ' in sentences (I am thinking about french or italian for instance).
str := "J'ai mangé un gâteau qui n'était pas frais"
VS
str := 'J\'ai mangé un gâteau qui n\'était pas frais"
What about HTTP/2 ?
Do you plan to implement it ?
I am curious about how you would serve HTTP/2 ressources in V.
from v.
@medvednikov coming back to our discussion about options some time ago:
Do you always have to return from the outer function? How do you just do default values, or equivalents for some of Rust's Option methods?
Can you write a small example?
Well essentially how would you translate all/any of Rust's or F#'s Option
methods into V? The Rust docs page I linked has tons of examples.
In Rust:
Some("four").map(|value| value.len())
// -> Some(4)
None.map(|value| value.len())
// -> None
fn vikings() -> Option<&'static str> {
Some("vikings")
}
Some("barbarians").or_else(vikings)
// -> Some("barbarians")
None.or_else(vikings)
// -> Some("vikings")
In F#:
Some "four"
|> Option.map String.length
// -> Some(4)
None
|> Option.map String.length
// -> None
let vikings =
Some "vikings"
Some "barbarians"
|> Option.orElseWith vikings
// -> Some("barbarians")
None
|> Option.orElseWith vikings
// -> Some("vikings")
from v.
@citycide none of these are supported.
Can you give me an example where you need to use Some("four").map(|value| value.len())
?
from v.
@medvednikov the point is you can operate on the value if it's present without needing to check if it's nil or missing, which is the entire proposition behind optional types / Option
.
Obviously you wouldn't typically create a Some
with a literal value like that before operating on it, the value would come from somewhere else. Then at the end of such a chain of map
s/filter
s etc. you'd use pattern matching or something like defaultValue "some default"
to branch on Some x
vs None
.
It seems so far that the doSomething()?
you've got here then is more like try { doSomething() } catch { return }
. Is that the extent of the feature?
from v.
Wouldn't it be possible to build options in as part of the standard library rather than as a core part of the language itself? At least without F#'s pipe operator.
I also see their usefulness and use them regularly with other languages, but a rich standard lib could be a better place. Perhaps a functional core library with other concepts to support purity could be nice as well (and something that I would be more than willing to contribute).
from v.
@citycide right now yes, the optionals are only used for error handling. I didn't like Go's err != nil
checks, so I implemented very simple optionals to handle them.
As you might have guessed I don't have much experience with them as I've never used a language with optionals before :)
@jkaye2012 I want them to be part of the language for simplicity and to avoid generics. Error handling is an integral part of development, and I want there to be one official way of doing that.
from v.
@medvednikov I see that it incorporates Rust's Result
, but I really don't see any Option
functionality at all which is what I've been trying to explore.
from v.
fn foo() Foo? {
if ... {
return None
}
return Foo{}
}
foo := foo() or {
println('None')
return
}
That's the only functionality right now.
from v.
I'll just have to see how it develops I guess — it's far better than Go's if err != nil
so I'm with you on that.
from v.
Related Issues (20)
- x.vweb: add gzip compression support for static files
- Compile time generation not working for maps in structs HOT 1
- incorrect values in interface reflection HOT 1
- x.vweb: gzip middleware can't be used if os is imported HOT 2
- ORM: `update table set field=field+1` is broken HOT 1
- watch: excessive memory usage [6gb...] HOT 2
- error library 'atomic' not found HOT 1
- compile error: value `100000000000` overflows `u32` HOT 3
- C. type unknown HOT 1
- Compiler Bug raised when trying to compile my code HOT 4
- [x.json2] Add skippable struct fields @[json: '-'] HOT 1
- Confusing error message when using `is` with a constant rvalue HOT 4
- Data corruption when initializing struct with 2-dimensional array of structs as a member HOT 4
- Better error message for memory allocation in vplayground HOT 1
- vlib: http.Server: different behavior between prod and non-prod for *invalid* Response object
- Builder error: bad map usage
- Different markdown rendering for enumerated list in module documentation HOT 2
- toml.parse_file does not panic when the file is missing HOT 2
- Will vweb have built-in Api document generation tools
- Optional type matches incorrectly in $for field
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from v.