[HN Gopher] Ziglings: Learn the Zig programming language by fixi...
___________________________________________________________________
Ziglings: Learn the Zig programming language by fixing tiny broken
programs
Author : DyslexicAtheist
Score : 389 points
Date : 2021-02-13 17:39 UTC (1 days ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| dleslie wrote:
| I really wish zig were a gcc frontend; the m68k and sh2 targets
| available in gcc make it desirable for a certain form of hobby
| programming.
| danielEM wrote:
| C target would solve it, I would be happy to use it with sdcc
| dleslie wrote:
| Ha, making gameboy games in zig would be neat.
| slimsag wrote:
| A few folks are working on gameboy emulators:
| https://github.com/nrdmn/awesome-zig#emulators
| dleslie wrote:
| That's not really the same as producing binaries that can
| function on original hardware.
| Bekwnn wrote:
| I'm not sure on the specifics of what you mean, but zig comes
| bundled with and wraps gcc. `zig cc` command directly forwards
| to gcc (try `zig cc --version`) and zig's build system can be
| used to build C programs.
|
| Zig currently is able to target quite a bit. There's a good
| chance you could open an issue and it would get added, or find
| an existing issue and see where it is on the roadmap.
| mkishi wrote:
| Zig ships with clang, not gcc.
| dleslie wrote:
| I was under the impression it was limited to llvm supported
| targets; of which m68k is not officially supported.
| aequitas wrote:
| To bad testing[0] isn't introduced in any of the examples. As
| breaking the compile step only get's you so far with generating
| interesting challenges.
|
| [0] https://ziglang.org/documentation/master/#Zig-Test
| account-5 wrote:
| If I wanted, as a complete novice, to learn a lower level
| language, where would be the best place to start.
|
| I always get confused by all these new languages. Ive heard of:
| nim, rust, D, V, and now Zig. Where do I start? Should I start
| with C or C++? Or pick one of these? But which one?
|
| Im currently looking at Lisp because I read it was good for alot
| of things. I'm also aware of Go and Swift but not looked into
| them at all.
| tigerlily wrote:
| Depends what you want to do. Starting with C is good, because
| then you get to learn the pitfalls, and hence understand the
| problems the other languages solve, and their advantages and
| disadvantages.
| kilburn wrote:
| What's your goal? Why do you want to learn a "lower level"
| language? Do you have experience in "higher level" languages?
|
| I would say that a better approach in your case is to start by
| saying "I want to write programs to solve problems like XXXX",
| or "I want to learn a language that lands me a job doing YYYY".
|
| For example, if you want to:
|
| - build network services -> golang
|
| - fiddle with OS level stuff (schedulers, memory management,
| etc.) -> C
|
| - write high performance calculation/simulation programs ->
| julia
|
| - get a nice solid base that can cover most of the above and
| has a promising future -> rust
|
| Nim, D, V, Zig are very niche and I wouldn't recommend as a
| first "lower level" language (because you'll have a harder time
| finding answers, and they won't give you clear benefits over
| the other options in any problem space).
|
| C++ is... huge. Modern C++ is a fine language, but you'll have
| to learn _a lot_ to be able to handle it.
| account-5 wrote:
| Im not what I consider a programmer though I can program. Ive
| most experience with Python, on Linux I use shell scripts but
| am no expert. On windows I use AutoHotKey, though I know most
| wont consider it a proper language.
|
| My main aim is really to learn about it. I wouldnt mind
| having a broad general experience in high level and low level
| before I decide to focus on anything in particular.
|
| I've started looking a compilers and how they work im working
| through a book about building a compiler. Im really just
| interested in whats going on in the background. I always find
| myself wondering about the implementations of the languages
| I'm using.
| kettro wrote:
| I agree with pron, C is the best starter here. It is simple
| enough to get your head around rather quickly, and has very
| defined concepts. The one place that gets people is pointers,
| but it's a very important part of software to understand.
|
| C is not "low level", in the assembly sense. It is absolutely a
| high level language. But it is the simplest, and the one with
| the most fine control.
| heldrida wrote:
| Zig is great as a first! Visit ziglearn.com, will get you
| started!
| pron wrote:
| Definitely start with C.
|
| Also, unlike the other languages you mentioned, Go and Swift
| aren't low-level languages. Low-level languages are those that
| give you very precise control over the machine instructions,
| almost as much as Assembly. Low-level programming is not as
| widely important as it used to be, because these days the cost
| of an instruction does not depend so much on what the
| instruction itself is but on the current micro-architecture
| state of the computer (e.g. which data is in which level of the
| cache; which branches are predicted and how) so even machine
| code is pretty high-level these days, but in some domains,
| especially memory-constrained environments, it is still
| irreplaceable.
| TazeTSchnitzel wrote:
| > Low-level languages are those that give you very precise
| control over the machine instructions, almost as much as
| Assembly
|
| By this definition I would say C is not "low-level"
| skohan wrote:
| Swift actually does effectively let you get fairly low level
| in the unsafe API, but for sure it's not the intended use-
| case for the language.
| haberman wrote:
| Neat concept. Exploring the difference between what successfully
| compiles vs. what won't seems like a great way of getting more
| familiar with the language.
|
| I've written a little over 1,000 lines of Zig at this point and I
| really like it. I think its key feature is a rich compile-time
| imperative programming environment ("comptime"). If you can have
| full compile-time imperative code execution, you can get a lot of
| the benefits of more complicated language features (like C++
| templates) "for free."
|
| In C++ templates are "a language within a language", but even
| templates with all their complexity cannot solve all of the
| problems you might want to solve at compile-time, so C++ has been
| gradually expanding its compile-time code execution features so
| that more and more of the language is available at compile-time
| (constexpr, consteval, etc). Zig jumps straight to the finish
| line by making most of the language available at compile-time
| from the outset, and in doing so avoids the need to add the
| complexity of templates in the first place.
|
| Having "slices" as a first class type feels like a general and
| powerful solution to the problems that std::string_view and
| std::span are trying to solve.
|
| I am comparing Zig to C++ a lot, which many Zig fans would
| probably take exception to as Zig does not aspire to be a better
| C++, but rather a better C. Indeed many key C++ patterns like
| RAII are explicitly out of scope. But to me Zig bridges the gap
| between C and C++ by solving many of the problems that make C
| feel too spartan without jumping to the incredible complexity of
| C++.
|
| There are a few things about Zig that give me pause. I've noticed
| that compile-time feels like a very lazy environment, meaning
| that functions do not seem to undergo full semantic analysis
| unless they are called from somewhere. You can write a function
| that compiles successfully, leading you to believe the function
| is syntactically and semantically coherent, only to find that
| when you add an actual _call_ to that function, the compiler now
| flags errors inside that function. This adds some friction to
| development, because the act of writing a function is no longer a
| self-contained activity. Writing the function feels more like
| sketching it; later when you actually call it you have a new set
| of compile errors to contend with.
|
| I also miss tools like ASAN to catch memory errors. I'm guessing
| things like that will come with time.
|
| Overall I feel very positive on Zig.
| klyrs wrote:
| > You can write a function that compiles successfully, leading
| you to believe the function is syntactically and semantically
| coherent, only to find that when you add an actual call to that
| function, the compiler now flags errors inside that function.
|
| This happens to me pretty frequently in C++. It won't compile
| with a syntax error, but if you don't call, say, a templated
| function, then the compiler simply can't know that the stuff
| you're doing inside is nonsense.
|
| I don't consider this to be friction. I generally know what
| I've called, and what I haven't. I expect dark code to be bug-
| ridden placeholders with good intentions.
| lenkite wrote:
| This will be fixed with C++ 20 concepts right ?
| IgorPartola wrote:
| One of the small but really good features of Zig that
| immediately stood out to me was the fact that there are no
| implicit function or method calls. _my.name_ will never call a
| hidden function. As useful as @property is in Python, it really
| makes it hard to reason about performance of code until you dig
| all the way through every bit of every class and type.
| Hoppetosse wrote:
| The standard library has a General Purpose Allocator that can
| catch some of the errors that ASAN can, like memory leaks.
| kristoff_it wrote:
| > I am comparing Zig to C++ a lot, which many Zig fans would
| probably take exception to as Zig does not aspire to be a
| better C++, but rather a better C.
|
| I was one of those people that started the idea that Zig should
| be compared to C more than C++. One day I'll express more
| clearly what I meant by that, but in the meantime I would say
| that Zig can and should be compared with C++ too.
|
| More generally I think we got to the point where Zig deserves
| to be analyzed in it's own right and not as a reflection of
| another language because, among other things, it leads to this
| kind of misunderstanding:
|
| > I've noticed that compile-time feels like a very lazy
| environment, meaning that functions do not seem to undergo full
| semantic analysis unless they are called from somewhere.
|
| Comptime's lazyness is a necessary feature and not an accident.
| This is how Zig can avoid having a macro system.
|
| More in general the idea is that you are supposed to write
| tests for your code, which will then ensure your functions get
| analyzed, and which in turn will produce documentation for your
| code. This makes testing more core to the development process
| than it is in other languages.
|
| I'm not saying everyone has to like this approach, but if you
| stop at the comparison with C, you risk missing how the design
| of Zig is able to spiral into an new and radical programming
| experience.
|
| See for example this Twitch clip from yesterday:
| https://clips.twitch.tv/RockyLivelyChimpanzeeDoubleRainbow-P...
| pron wrote:
| Totally. Zig is neither a better C nor a better C++, but an
| entirely new (and better, IMO) concept for how low-level
| programming can and should be done. Zig is about as simple as
| C and as expressive and powerful as C++, but it doesn't
| follow either's design tradition (unlike Rust, which is very
| much in the C++ tradition), and should only be compared to
| either one by virtue of all three being low-level languages.
| dnautics wrote:
| > Zig is neither a better C nor a better C++, but an
| entirely...
|
| I agree with your point because zig has evolved, but I do
| think that it is important to note at least for historical
| purposes, that zig was created literally as a "better c",
| and a lot of decisions are made because of some specific
| pain point X or Y in c
| fpoling wrote:
| What is C++ tradition? Is it that one does not pay for a
| feature unless one uses it? In practice C++ broke with that
| with exceptions and RTTI. Even Rust does adhere to it since
| its standard library assumes infallible allocations making
| one to pay for not relying on it in the form of having to
| write an alternative library.
| pron wrote:
| In all low-level languages you don't pay for what you
| don't use; that's not a design tradition but a
| requirement of the domain. I'm talking about the
| tradition of a low-abstraction, low-level language that
| has many features so that, when it is read on the page it
| appears as if it were high-level.
| pjmlp wrote:
| That would be the case if one wasn't allowed to turn them
| off.
| fpoling wrote:
| The standard library of C++ assumes exceptions and that
| dictates code style that, even if one assumes infallible
| allocations and disable exceptions, one gets suboptimal
| code. So even with exceptions off one pays the price
| either in the form of non-standard library or accepting
| non-optimal performance. And if one has to prepare for
| fallible allocations, then the standard C++ is of no use
| at all in practice.
| Quekid5 wrote:
| > So even with exceptions off one pays the price either
| in the form of non-standard library or accepting non-
| optimal performance.
|
| Holy moving goalposts, batman!
|
| The "don't pay..." thing has only ever applied to
| runtime, there nothing in there about not having to write
| more code yourself, etc.
|
| (It's also a bit dubious in the first place. Chandler had
| a good talk about this at one of the CppCon's, IIRC.
| Can't be bothered to look it up, but it should be on
| YouTube.)
| pjmlp wrote:
| I assume you aren't that comfortable with ISO C++, the
| standard does allow for failible allocations.
|
| That is the role nothrow in placement new, and custom STL
| allocators as language tool.
|
| Additionally plenty of APIs now have exception and error
| based versions with noexcept.
| fpoling wrote:
| The fallible allocators require to use exceptions. There
| is no way to use, for example, C++ containers with
| fallible allocators and disabled exceptions.
|
| But even with exceptions enabled fallible allocation in
| practice does not work. There was an article that made
| malloc to return null randomly. All tested C++
| implementations crashed then because they allocated
| memory when generating exceptions.
| pjmlp wrote:
| Stop talking in circles and point out ISO C++20 sections
| then.
|
| I am also curious to see how serious was that article.
| fpoling wrote:
| http://www.open-
| std.org/jtc1/sc22/wg21/docs/papers/2019/p070... - this
| discusses a lot of issues with exceptions as in ISO C++
| and concrete proposals to make exceptions cost-free. The
| section 4.3.5 discusses specifically memory allocations.
| pjmlp wrote:
| Including parts that relate to Linux, have nothing to do
| with C++ and apply to any programming language.
|
| You also skipped the section where Rust in its present
| state doesn't has any kind of recovery, it just panics.
| haberman wrote:
| I'm not sure how my statement was a misunderstanding if you
| are confirming that function analysis is in fact lazy.
| kristoff_it wrote:
| The misunderstanding lies in not realizing how lazy
| evaluation is an integral part of what makes comptime a
| useful tool and that removing it would break comptime
| horribly.
| haberman wrote:
| That seems a bit of an overstatement. Calls to sometimes-
| unavailable functions are but one of the many uses of
| comptime. It seems entirely possible that lazily-analyzed
| blocks or functions could be demarcated syntactically
| (eg. "lazy { }") and that the large majority of comptime
| evaluation would not need to be inside such a block.
| aarchi wrote:
| > Comptime's lazyness is a necessary feature and not an
| accident. This is how Zig can avoid having a macro system.
|
| Can you elaborate on lazy analysis replacing the need for
| macros?
| defen wrote:
| C macros are lazy, but they also operate at the level of
| lexical tokens instead of the AST, which means you can use
| macros to generate C code, but you can't really do it in a
| way that is guaranteed to be safe.
|
| With Zig you can have a function where some or all
| arguments are marked as "comptime", which means the values
| for those arguments must be known at compile time. Combined
| with the fact that types can be used as values at compile
| time means that you can use Zig to generate Zig functions
| in a safe way.
| dralley wrote:
| https://www.youtube.com/watch?v=Gv2I7qTux7g&t=17m10s
| Quekid5 wrote:
| I'd appreciate some elaboration on that too. It sounds
| vaguely similar to SFINAE in C++, but I don't know enough
| about Zig's compilation model to know for sure.
|
| (I'm vaguely familar with Zig from a talk by the creator
| about 11/2 years ago, fwiw.)
| kristoff_it wrote:
| Lazyness is what allows you to write code that feels
| naturally coherent but that would be an error with eager
| analysis. As an example:
| switch(build.target.os) { .Linux => std.os.fork(),
| .Windows => std.os.funcUniqueToWindows(), else =>
| @compileError("feature not supported for target os"),
| }
|
| This a simplified example to say that each path that
| depends on a comptime condition, such as the target OS, for
| example, feels intuitively consistent but in Zig types can
| (and do) mutate depending on those conditions and if the
| compiler were to eagerly check dead branches it would find
| plenty of semantical errors. In the stdlib you can see how
| `os` corresponds to a different struct definition depending
| on the target: https://github.com/ziglang/zig/blob/master/l
| ib/std/os.zig#L5...
| AndyKelley wrote:
| This definitely does cause problems though; I want to
| acknowledge that. For example, right now we have an issue
| that auto-generated documentation does not include
| unreferenced globals.
|
| I have some ideas to address this, but it does represent
| a flaw in the status quo design of the language.
| JacobCarlborg wrote:
| In D, all semantic analysis is performed eagerly (I
| think), except for templates. D also supports CTFE
| (Compile Time Function Evaluation), `static if`, `static
| assert` and a few other language constructs that are
| evaluated at compile time.
|
| I experimented a bit at how D's documentation generator
| behaves using these language constructs. Here's a snippet
| of some D code: /// some struct
| description struct Foo(T) // template {
| /// some alias description alias Result = int;
| /// some method description Result foo()
| { string a = 3; // this does not normally
| compile } static if (is(T ==
| int)) // evaluated at compile time {
| /// some method description 2 void bar() {}
| } version (Windows) {
| /// some method description for Windows
| void bazWindows() {} } else
| version (Posix) { /// some method
| description for Posix void bazPosix() {}
| } else static
| assert(false, "Unsupported platform"); // evaluated at
| compile time }
|
| When generating documentation for the above code, and
| `Foo` has not been instantiated, the generated docs will
| include `Foo`, `Result`, `foo`, `bar`, and `bazWindows`.
| This is regardless of platform. The return type of `foo`
| will be `Result` and not `int`. This clearly shows that
| the D compiler doesn't perform semantic analysis when
| generating documentation. When doing a regular
| compilation and `Foo` is instantiated, `bar` will only be
| included if `T` is an `int`. `bazWindows` will only be
| compiled on Windows and `bazPosix` will only be compiled
| on Posix platforms.
|
| Looking at the implementation, the compiler will generate
| the docs after semantic analysis and only if there are no
| errors. But, if `Foo` is never instantiated no errors
| have occurred so it will continue to generate the docs.
|
| On the other hand, if `Foo` is instantiated (and
| compiles) the compiler will generate docs for the AST
| after semantic analysis has been performed and
| `bazWindows` will only be included if the docs were
| generated on Windows and `bazPosix` will only be included
| on Posix platforms. What's weird though, is that it seems
| `bar` will be included regardless of what type `T` is.
| IgorPartola wrote:
| But you can still check the syntax of that statement
| without evaluating it all. You might even be able to
| check if things like std.os exist.
| vram22 wrote:
| Is Zig's comptime feature like D's CTFE?
| fpoling wrote:
| Zig compile-time evaluation even allows to construct an
| arbitrary type like a struct with a platform-specific members
| all using the same core language. This beats even Rust macros
| and in retrospect I wonder why this not used in other
| languages? Even Lisp ended up with macros with own sub language
| instead of making the core language more useful for code
| generation. Or consider Go attempts at generics. Something like
| Zig approach will fit it more I think than various generics
| proposals.
| afranchuk wrote:
| I would guess one reason it wasn't done in other languages
| was because people simply didn't have a good cross-
| architecture JIT compilation resource, and didn't want to
| write it themselves. LLVM makes this _really_ easy. I realize
| that Zig is transitioning to an LLVM-optional model now. But,
| for instance, I've been working on an s-expr language with
| f-expr application, and this combined with LLVM c bindings
| allows you to generate arbitrary compile time or runtime
| code. The JIT portion for compile time code was a single
| function call in LLVM! I started this a while before Zig came
| out, but alas I haven't devoted enough time to it over the
| years...
| haberman wrote:
| I agree it's an idea that seems so natural in retrospect that
| I'm also curious why it hasn't traditionally been more
| popular. One possible reason that comes to mind is that an
| imperatively-constructed type is harder to statically
| analyze.
|
| But on the other hand, even C++ templates are Turing complete
| and even C++ parse trees can depend on the output of a
| Turing-complete evaluation. So it is hard to see what benefit
| a C++-like template feature is buying in comparison.
| fpoling wrote:
| Even Java and Rust ended up with Turing-complete generics.
| bobthebuilders wrote:
| Java turing complete generics are an edge case though,
| and never hit during normal compilation.
| fpoling wrote:
| Still the compiler has to deal with that. So one ends up
| with an interpreter in the compiler for very esoteric and
| hard to write/read language instead of just embedding an
| interpreter of a subset of Java.
|
| One alleged benefit of Java constrained genetics is that
| they allow in theory better error messages. Still in
| complex cases even after over 15 years with genetics in
| Java the error messages are not that great. Zig to some
| extend delegates to the compile-time library authors
| responsibility of producing good error messages. But then
| the error messages can be improved without waiting for
| the compiler to improve its reporting heuristics to cover
| all edge cases.
| bobthebuilders wrote:
| Incorrect Java does not have genetics. That is a C++
| concept.
| pron wrote:
| Not only was it not "more popular," I am not aware of even
| research languages taking the idea of general-purpose
| partial evaluation _not_ through syntax macros to the same
| lengths as Zig (although that doesn 't mean there weren't
| any). It's possible that no one had thought of that,
| perhaps because type systems, while known to be possibly
| considered as a form of partial evaluation, are generally
| treated and studied as a completely separate concept:
| partial evaluation is a compilation technology while types
| are part of the theory.
| throwaway17_17 wrote:
| I'm not clear on what you define syntax macros, but the
| compile time evaluation that is present in Zig (based on
| the example and documentation I've seen) are an almost
| direct implementation of the multistage computation
| research done late 90s-mid 00s. The papers and such are
| typically ML based (with a caveat for the early Template
| Haskell paper in 02) and the underlying constructs of
| MetaML are very close to what Zig implements. All this
| work is retroactively semantically underpinned by Rowan
| Davies and Frank Pfenning work on Modal S4 logic. I don't
| know if Andy based Zig on this research, but if he
| didn't, the convergence toward the same theory is a great
| thing to see.
|
| My current work on a visual programming compatible
| language also uses this strategy for meta programming, so
| I'm very familiar with the academic literature. It
| certainly seems that Zig got this right and is doing well
| implementing it in a way that is usable and
| understandable.
| pron wrote:
| By syntax macros I mean expressions that can be
| referentially opaque, i.e. m(a) and m(b) might have
| different semantics even though a and b have the same
| reference. Lisp (and C, and Haskell, and Rust) is
| referentially opaque while Zig is transparent. Opacity is
| strictly more expressive, but is harder to understand;
| Zig strives to be the "weakest" language possible to get
| the job done.
|
| MetaML certainly does seem to be similar to Zig, although
| the one paper I've now read thanks to your suggestion (ht
| tps://www.sciencedirect.com/science/article/pii/S03043975
| 0...) does not mention introspection and type functions,
| and another commenter here suggests that it is, actually,
| referentially opaque.
| ymbeld wrote:
| It doesn't seem as general as MetaOcaml. Just two-stage
| evaluation, and without quote and splice.
| throwaway17_17 wrote:
| I think (again based on examples and docs) that it is
| actually multistaged. However, this is not apparent
| because the quote and splice are semi-implicit. The
| 'comptime' keyword is essentially a the quote operator,
| ie. it produces what is essentially a compile time thunk,
| lazily capturing the 'code' value of the expression
| defined under the comptime keyword. This thunk is
| directly analogous to a value of type 'code a' in MetaML.
| Then there is an implicit splice operator in place any
| time a value defined under comptime is used subsequently.
| I say it is multistaged because it certainly appears that
| one can define a comptime variable for some computation
| and then use that variable in a later comptime definition
| or expression. So, it looks like a basic data flow
| analysis to determine dependency is done on the comptime
| evaluations and those are ordered implicitly. This order
| would correspond to the more explicit staging syntax of
| MetaML and the operation semantics that underpin it.
| pron wrote:
| I think Zig's comptime has three interesting features:
|
| 1. It is referentially transparent, i.e., unlike Lisp,
| i.e. nothing in the language can distinguish between `1 +
| 2` and `3`. This means that the semantics of the language
| is the same as if everything was evaluated at runtime,
| and the comptime annotation has no impact on semantics
| (assuming syntax terms aren't objects and there's no
| `eval`).
|
| 2. It supports type introspection and construction.
|
| 3. It doesn't have generics and typeclasses as separate
| constructs but as applications of comptime.
|
| I think 3 is unique to Zig, but I wonder about 1: is it
| possible in MetaOCaml, as it is in Lisp, C, C++, Rust and
| Haskell -- _but not in Zig!_ (or, say, Java) -- to write
| a unit `m`, such that m(1 + 2) is different from m(3)?
| ymbeld wrote:
| I don't know. I think MetaOcaml is strict about
| inspecting Code terms like Code (1 + 2) and Code 3 (as
| far as I remember it is not allowed). So no, I don't
| think you can distinguish between them.
| haberman wrote:
| > I am not aware of even research languages taking the
| idea of general-purpose partial evaluation not through
| syntax macros to the same lengths as Zig
|
| One that comes to mind is Terra: http://terralang.org/
|
| In retrospect Terra seems a clear precursor to Zig
| (though I don't know if it was a direct influence).
| pron wrote:
| I've heard of Terra, but I didn't know it had predated
| Zig by a couple of years; thought they were introduced at
| about the same time. And yes, there are certainly
| similarities, although Terra thinks of itself as two
| interoperating languages, while in Zig there is just one
| (although there are things you can only do in comptime so
| perhaps it's more of a difference in perspective).
| ymbeld wrote:
| The term partial evaluation tends to be used for research
| that focuses on automatic evaluation of the static part
| of the program. When considered as metaprogramming the
| research would probably discuss type-checking +
| evaluation as two-stage evaluation, falling under the
| general umbrella of multi-stage programming.
| jeltz wrote:
| Tow issues I have noticed with Zig: not as good type
| signatures for functions and not as good error messages. I
| am not sure if those are fundamental issues with Zig's
| apporach or if they can be fixed with more work.
| vram22 wrote:
| Can you elaborate a bit on the first issue?
| mhh__ wrote:
| We have a slightly vague proposal in D to basically construct
| programs as a library at compile time (i.e. we give you an
| AST, you play with it and give it back, if it's valid it.gets
| turned into a type).
|
| D has been making structs at compile time for years now,
| however.
| gmfawcett wrote:
| "Even Lisp ended up with macros with own sub language..." I
| assume you're talking about Scheme approaches like `syntax-
| case` and `syntax-rules`? In Common Lisp, macros are written
| in Lisp, the same way you would write runtime code. Unquoting
| and splicing are part of the core language (e.g. they can be
| applied to data as well as to code).
| fpoling wrote:
| I was not aware that unquoting in Common Lisp can be
| applied to data. So it is not a specialized sub language
| just for macros, but a general purpose template system that
| could also generate code.
| ywei3410 wrote:
| It's really a shorthand for writing lists - sexp's are
| lists, so can use the same syntax.
|
| Macro's in Lisp are essentially "just" functions where
| the arguments are un-evaluated - you can use all the same
| functions etc...
|
| Writing a simple Lisp interpreter is really quite
| educational - when you add macros and quoting into the
| language, you suddenly have a realisation at how simple
| it is.
| kazinator wrote:
| That's right. There is no difference between:
| (defmacro my-quote (x) `(quote ,x))
|
| and (defmacro my-quote (x) (list
| 'quote x))
|
| That `(quote ,x) is just way of writing (list 'quote x),
| not a notation for writing macros.
|
| That's it.
| JacobCarlborg wrote:
| This is very common in D and D doesn't not have any macro
| system. It uses regular syntax (more or less). D was doing
| this way before Zig existed and before C++ had constexpr.
| Simple example of platform specific members:
| struct Socket { version (Posix)
| int handle; else version (Windows)
| SOCKET handle; else static
| assert(false, "Unsupported platform"); }
|
| Another example is the checked numeric type [1] in the D
| standard library. It takes two types as parameters. The first
| being the underlying type and the second being a "hook" type.
| The hook type allows the user to decide what should happen in
| various error conditions, like overflow, divide by zero and
| so on. The implementation is written in a Design By
| Introspection style and inspects the hook type and adopts its
| implementation depending on what hooks it provides. If the
| hook type implements the hook for overflow, that hook will be
| executed, otherwise it falls back to some default behavior.
|
| [1] https://dlang.org/phobos/std_experimental_checkedint.html
| smallstepforman wrote:
| I'm interested in exploring Zig, but the draconian measure to ban
| hard tabs is pushing me (and many others from what I've read
| online) away from it. Andrew, get off your high horse, allow hard
| tabs, and we can all join hands and work together.
| anand-bala wrote:
| I think the whole point of picking a language standard is to
| prevent the "space vs tabs" debate. Andrew is trying to
| standardize the language formatting issues, similar to tools
| like `rust fmt`, `gofmt` and `black`.
|
| The "Spaces vs. Tabs" argument shouldn't be what stops you from
| joining hands and working together :)
| simias wrote:
| I completely agree with you, I love not caring about
| formatting anymore. That being said, does this mean that zig
| refuses to compile code containing tabs? Because that seems a
| bit counterproductive to me.
|
| A great advantage of rustfmt and friends is that I don't
| really have to care about my editor being correctly
| configured, I can just code without worrying about style and
| run rustfmt before comitting. But if the compiler outright
| rejects poorly formatted code it means that I have to run the
| format tool every time I want to compile or risk having my
| code rejected due to format issues. Now I have to care about
| my style again! It's the opposite of what I want.
|
| I mean it's a very small issue and mainly a bikeshed, but
| that seems like an odd decision to me.
| ymbeld wrote:
| "Refuse to compile" makes it sound like the compiler is
| able to but unwilling to compile the code. It could very
| well be that the parser doesn't recognize tab as a valid
| token.
| m45t3r wrote:
| You can just configure your editor to run formatter on save
| or with a shortcut. Not really a deal breaker.
| anand-bala wrote:
| You have a valid point, but if the only formatting issue
| you will have is tabs, then running `zig fmt` on your
| codebase is pretty much a non-issue.
|
| If your project is small, just run `zig fmt` on the command
| line.
|
| If you have a large codebase, you can just incorporate it
| into your build process (similar to how clang-format and
| clang-tidy are used in CMake projects).
|
| But again, if you have a large codebase written in Zig,
| you've probably already configured your editor to run `zig
| fmt` on save :)
| littlestymaar wrote:
| > But again, if you have a large codebase written in Zig,
|
| At this point it means you're probably Andrew himself
| because the Zig compiler is the only large Zig codebase
| out there;)
| jorangreef wrote:
| https://github.com/ifreund/river
|
| https://www.youtube.com/watch?v=124wdTckHNY
| mssundaram wrote:
| You're saying this from atop your own high horse.
|
| I used to fight about prettier (js) gofmt and so on. I just
| finally found I don't care. It's more fun to just code and
| watch it all get autoformatted to the project or language
| standard
| smallstepforman wrote:
| The reason hard tab people dislike code editors which convert
| to spaces is that pressing backspaces during editing removes
| one space, not all auto-inserted spaces. This ends up being
| very frustrating (since you need to press backspace 4 times).
| Most "used" languages allow both. Accept tab as another white
| space character and life goes on. Compile errors for hard
| tabs is a stubborn decision.
| kortex wrote:
| Any editor worth it's salt will indent with tab and de-
| indent with shift tab with the cursor at the first non
| whitespace. Any _good_ editor will de-indent with the
| cursor anywhere on the line.
| dnautics wrote:
| > The reason hard tab people dislike code editors which
| convert to spaces is that pressing backspaces during
| editing removes one space, not all auto-inserted spaces
|
| This is simply not the case for any editor I have used
| recently.
| sedatk wrote:
| In addition to this, "de-indentation" can be achieved
| with Shift-Tab instead of backspace.
| zamadatix wrote:
| If tabbed indetation not being supported by the stage1 compiler
| is enough of a reason to not use a language it's probably best
| for zig to avoid those that would make this type of feedback
| and vice versa until stage2 and the language are stable (both
| support tab indentation, they just aren't finished).
|
| I'm solidly in the tabs camp myself I just understand
| bikeshedding about this class of issue isn't what zig wants
| to/should be worrying about at the moment while core components
| are still being shifted around and written. In the meantime
| "zig fmt" runs as part of my build and life moves on.
| travisgriggs wrote:
| I keep meaning to look into zig more. Can it be used for embedded
| chips like M0s yet?
|
| I'd love to hear if anyone's cross compiling to embedded chips in
| any real projects with it. Or it's strongest play still command
| line tools on Linux?
| hansvm wrote:
| Zig is still "not production ready," embedded is still rough,
| and you might have to contribute to Ziglang itself to get any
| particular architecture working appropriately. That said, yes
| people are using Zig a little for embedded stuff:
|
| https://codelv.com/blog/2020/5/using-zig-and-the-stm32h7-to-...
|
| https://www.mdeditor.tw/pl/2Ap9
|
| Xtensa is less supported. M0 might also have some issues:
| https://github.com/Schroedingers-Hat/xtensa-zig
|
| I've been meaning to try it out for embedded myself; I'll let
| you know how it goes.
| [deleted]
| leetrout wrote:
| I wish these types of projects would identify themselves as koans
| in the README or something. Makes it much easier to surface
| exercises like this when googling.
|
| I think this is the best way to learn languages.
|
| Does anyone know of any for TypeScript?
| jamesholden wrote:
| I saw your comments and I was thinking to myself.. "They should
| have one for Regex (regular expressions). That would be a cool
| way to learn it."
|
| Apparently someone did. -\\_(tsu)_/- TIL
|
| https://regex101.com/
| nick__m wrote:
| Regex101 is especially useful, I use it to check for
| catastrophic backtracking1 before committing a regex.
|
| 1-https://www.regular-expressions.info/catastrophic.html
| markbnj wrote:
| I have regex101 open in a tab any time I am developing a
| regex :). It's an awesome tool, and I especially appreciate
| the mini language reference in the lower right corner of the
| window.
| BasedInfra wrote:
| Never heard of koans before, it's a brilliant idea for learning
| a new language.
|
| Opportunity for a index or site for koans.
| danpalmer wrote:
| Koans are a fairly well-known technique, and if you Google
| "<language> koans" you'll find something for most languages.
| I like it as a learning style.
| gmfawcett wrote:
| Let's hope that nobody invents a language called Zen --
| they will run into problems. :)
| kristoff_it wrote:
| if you want to have a laugh, check the news section of
| ziglang.org. There was also a pretty big discussion on HN
| at the time.
| gmfawcett wrote:
| Hah! I didn't know of any Zen languages -- just to find
| one a stone's throw away from Zig. Thanks for pointing
| that out.
|
| (And that news story... what an absolute mess of a
| situation.)
| davegauer wrote:
| You're absolutely right. My own first exposure to this type of
| learning resource was Ruby Koans. I believe Rustlings (which
| was my direct inspiration) also credits RK. I'll update the
| README with the grandparent attribution. :-)
| yarinr wrote:
| https://github.com/typescript-exercises/typescript-exercises
| maddyboo wrote:
| I love these sorts of resources! I just created an "awesome
| list" [1] to keep track of resources specifically centered
| around learning by example. I've only got a few so far, several
| of them being from this thread. Contributions welcome!
|
| [1]: https://github.com/b0o/awesome-by-example
| jedisct1 wrote:
| This is a very good idea!
|
| A nice way to discover a very promising language.
| yoshuaw wrote:
| Heh fun: this was inspired by Rustlings, which in turn was
| inspired by NodeSchool.
|
| Mozilla Berlin used to host NodeSchool and the Rust Hack & Learn
| evenings. It became a bit of a hang spot, and at some point we
| had a pretty consistent group of folks who'd go to both. Marisa
| realized Rust could use something similar to NodeSchool, and
| started hacking on Rustlings during these evenings -- which now a
| few years later has really taken off!
|
| It's really cool to now see other languages in turn be inspired
| and follow from Rustlings ^^
___________________________________________________________________
(page generated 2021-02-14 23:02 UTC)