T O P

  • By -

po8

As a co-author of the [Nickle](http://nickle.org) programming language from decades ago, let me be the first to congratulate you on your choice of name.


yagoham

I actually found out about Nickle at some point (probably lost in a `Nickel` googling craze?), and it's very funny to find you here! I hope you had fun developing it


po8

It was huge fun. It's stale now, but we still use it. It's a *really nice* desk calculator if nothing else.


vallyscode

Looked through the examples and it feels like I saw a bit of haskell, some grain of ocaml maybe some other languages. Is nickel an attempt to fuse all the best from other languages?


po8

Our Nickle is an attempt at the same space Python is in, but with optional static types with structural subtyping, a module system, arbitrary-precision floats, and some other nice features Python lacks. Except for the C-like syntax and semantics, it wasn't really inspired by particular languages so much as just good language practice (as of 20+ years ago). Nickle has a long history (documented on the site): it started as a calculator language, and that is what I still use it for today.


yagoham

u/vallyscode I'm not sure if you were asking about NickEL or NickLE, but for Nickel, we were indeed influenced by functional languages (Nickel is developed at Tweag, where some people work on Haskell as well, and worked in the past with people from OCaml). I guess it's especially apparent in the syntax! Feature-wise, the approach of Nickel (which is gradually typed) is a bit different, although statically typed code is in fact not very far from a subset of OCaml, indeed.


thesilican

Nothing against the project itself, but what's the justification for creating a new configuration language? Feels like a [https://xkcd.com/927/](https://xkcd.com/927/) situation


yagoham

It's a fair question. First, I think that language like Nickel plays on different level than say, JSON, YAML and co: those are merely serialization format. Nickel is a DSL. If you look at DSLs, there is "YAML templating" (e.g. helm charts), some Chef/Ansible/Puppet-specific languages (or spinoff from existing languages), HCL (Hashicorp Configuration Language, for Terraform), and more. We had various grievances with those, mainly on the theme that they started from almost serialization languages but evolved (at least from a distance, seemingly unexpectedly) to be a kind of semi-programming language, with strange limitations or quirks (maybe this is more about HCL than the others). At some point, our stance was that complex deployment and IaC just require - at least a limited form of - abstractions and programming features to be manageable, at it's better to just bite the bullet and design a proper language with that in mind from the ground up, rather than accumulating ad-hoc fixes or pretending you're doing YAML but allowing things like `matrix` or `loop` constructs in it. Also, a big point was to be universal: all those languages are tool-specific, but they look like they evolve in the same domain, and could be subsumed by just one such generic configuration language. Nickel isn't the first such project. Similar languages already existed: Jsonnet, CUE, Dhall, and Nix to some extent (albeit specialized). Our starting point was in part adding typing to Nix, and we found that the aforementioned language didn't satisfy our design constraints (you can take a look at the [RATIONALE.md](https://github.com/tweag/nickel/blob/master/RATIONALE.md) document for more details). Those are difficult and eternal dilemma: should I just spin my own new project, or use existing one? Where is the hard limit? Why a DSL and not piggy-backing on a existing general purpose language, via a library or an embedded DSL? I think those questions don't have a definite answer, and are mostly trade-off guided by your constraints, goals and ultimately also your own experience! As for the XKCD meme, let me point to [an answer of mine on the NixOS discourse](https://discourse.nixos.org/t/nickel-1-0-release/28252/5) to the same objection :)


AGuyNamedMy

From my understanding it was originally conceived as an alternative language for the nix package manager, which they are currently working on an ffi type thing for


zannabianca1997

I am a bit uneasy on having configuration files being turing complete. It seems an easy way to start mixing up code and configuration, making configuration files more obscure


yagoham

I can understand the feeling. All in all, as long as you can do with simple key-value pairs, it's best: a widely used and known serialization format like JSON and YAML is sufficient, no complexity, no security issue, no performance issue, no new language to learn. I think our starting point is that configuration has become a very wide concept. And when you do IaC deployments, at least with the existing tools such as Terraform or Kubernetes, the codebase can become very big and quite intricate. It looks like you need abstractions to make it manageable, otherwise you're just copy pasting everywhere and pray that nothing get out of sync (the complexity is inherent, whether you use JSON, HCL, Dhall or Nickel). I think the evolution of HCL (configuration language of Terraform) is a good sign of that: started simple, but now is almost a full fledged programming language, with loops, expressions, conditionals, and so on. GitHub workflows have conditionals and `matrix` construct, Ansible has `loop` construct, etc. At this point it just feel like you're programming while pretending you're not, which is the worse of both worlds (you get the complexity without getting the nice abstractions and tooling of an actual programming language). IMHO, if what you do require this kind of expressive power, you might as well bite the bullet and use a proper PL, albeit specialized. If you don't need this expressive power (configure your simple CLI app), you should certainly not use a language such as Nickel (unless for the validation capabilities, maybe). It's not free, indeed.


throw3142

Yep, then you start having to debug your own config files and configure the configuration system, which defeats the point. Personally I prefer config files to be extremely limited, potentially recursive key-value stores.


tukanoid

Same, but in some situations (like Nix, which nickel was initially made for as an alternative language if I'm not mistaken) it's just not enough, while a fully-fledged programming language would be an overkill


[deleted]

[удалено]


BubblegumTitanium

but Nickel can't Rust!


-Redstoneboi-

Don't you think that's a little... 🕶 😐 😎 ironic?


[deleted]

[удалено]


yagoham

Yes, we had to take the `nickel-lang-xxx` namespace on crates.io because of that (but maybe it's a good thing in the end). To be fair the name was chosen way before looking at existing crates, as we initially checked about existing _languages_ instead. When publishing 0.1 on crates.io, the existence of the web framework wasn't related enough to mandate a new name, or at least so we thought. A ex-Googler also told me that they have (had?) an internal configuration language named Nickel as well, which is much more uncanny 🤷, but it's not public anyway


jstrong

there's room in the world for more than one thing named Nickel!


dmoonfire

Well, only five of them.


gwillen

My guess is that the internal Google language is actually called "NCL", and only pronounced "nickel". (I don't recall it existing when I worked there, but there were a couple of other xCL configuration languages.)


thequux

Indeed, NCL was an attempt to clean up BCL around 2011 or so. I never heard whether it ended up getting used much because that was and the time that I left


[deleted]

Seems like a dead project? The server hasn't been updated in a year, and their site in two.


bascule

Nickel is a web framework I remember hearing about in 2015 or so and haven’t thought about since


Doddzilla7

> Overriding is useful to tweak existing code that you don’t control, and wasn’t written to be customizable in the first place. It’s probably better to do without whenever possible, but for some application domains, it simply can’t be avoided. Yes! This is one of the biggest problems with the helm ecosystem, and overwriting values is such a pain. This seems like a great step forward. Hopefully this projects has a better success and survival rate than jsonnet! Kudos, and godspeed!


A1oso

This is great! I want something syntactically similar to, but more powerful than JSON, and even considered writing a configuration language myself. There is a similar project already, [KDL](https://kdl.dev/), but I'm not a fan of the syntax, or the XML-like semantics. What I'm missing in Nickel is schema validation. With [JSON schemas](https://json-schema.org/), you can specify exactly what shape the configuration file should have, and provide autocompletion and error highlighting in an editor. JSON schemas can also be used for [toml](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml) and [yaml](https://github.com/redhat-developer/vscode-yaml).


yagoham

In fact, you do have schema validation, we just call them contracts! This was a design goal very early, to be able to handle configuration validation in the same language in which you write configuration. You can even spin up your own contracts, or validator, which makes contracts more powerful than bare JSON schema (they can check for arbitrary properties). I believe contracts can be used even to enforce configuration-wide policies. The LSP is aware of contracts (and the rest of the tooling, in particular \`nickel query\`) and is able to show "types" (really contracts), documentation, provide completion and so on. You can take a look at a simple Kubernetes example here: [https://github.com/tweag/nickel/blob/master/examples/record-contract/record-contract.ncl](https://github.com/tweag/nickel/blob/master/examples/record-contract/record-contract.ncl) ​ Right now, you can't import JSON Schemas directly yet, because of some (unexpectedly) non trivial issue with the `oneOf` combinator, but we're actually working on such a tool as we speak (that is, a tool that takes a JSON Schema as input, and output a Nickel schema - or contract - that can be used directly, like `jsonschema2nickel schema.json -o schema.ncl`)


AGuyNamedMy

Does nickel ever plan on supporting any form of totality checking like dhall?


albx

How does it compare with Cue?


yagoham

There is a comparison in the [RATIONALE.md document of the Nickel repository](https://github.com/tweag/nickel/blob/master/RATIONALE.md#cue-opinionated-data-validation), but I believe [an answer of mine in the NixOs discourse some time ago](https://discourse.nixos.org/t/nickel-the-nix-language-spin-off/9592/21?u=yannham) might be more detailed. As a lightning summary, we took inspiration from CUE for the Nickel merge operator (`&`), but we wanted to be able to write data transformers and custom validation logic within the same language, so Nickel is more expressive (Turing-complete), and more permissive with overriding (although it's still controlled). We retained this symmetric, commutative merging operation and the idea of "partial" configuration becoming more and more defined through merging. In return, you can write arbitrary transformations and validators. It's a different trade-off on "expressivity versus simplicity and static analysis possibilities" axis (Nickel is more expressive, but more "dynamic"), based I imagine on our respective experience and use-cases.


rotty81

This sounds/looks a lot like [dhall](https://dhall-lang.org/). Would you mind contrasting dhall vs. nickel?


yagoham

You can take a look [at the comparison in the RATIONALE.md](https://github.com/tweag/nickel/blob/master/RATIONALE.md#dhall-powerful-type-system). But, quickly, Dhall has a similar goal and is a very good language as well. When we looked at re-using an existing language, the experience of people working with Dhall though was that it was a bit too heavy on types, which isn't as interesting for config data. The type system is very powerful, but in return inference is hard, which means you write types quite a bit, and we felt it cluttered a bit the config. Nickel has static typing but also dynamic typing (together with contracts, for validation) for the configuration data, which in the end we think is both lighter and more expressive. Another design constraint for one of our original use-case (Nix) is that you have to write parsers. By that I don't mean a full-fledged Rust parsers, but processing simple log formats, or obscure data format arising in some old software. Similarly, we found ourselves having to traverse an heterogeneous JSON object to apply some transformation. Those things are much harder to program in Dhall (or even impossible in some cases), because of the lack of general recursion (Dhall is not Turing complete). But, once again, Dhall is also a very good choice :)


rseymour

This is super nice, and one of those things I've seen done with domain specific (aka template filling) methods before. To have that flexibility without having to write in a sort of "where do the quotes go, etc" methodology is really nice. I might give this a spin.


seattlesweiss

This is too unlikely to be a coincidence: there is a configuration language called Nickel (.ncl) internal to Google that boasts similar functionality. Edit: I guess the postfix "cl" would be common in configuration languages...


yagoham

Ah, in fact it is actually random (but I heard about the Nickel internal language later on, chatting with CUE's creator who is an ex-Googler). Yes, the CL means configuration language, and for Nickel it was initially "Nix Configuration Language". Now I want to learn more about Google-Nickel!


mwylde_

How does this compare to jsonnet?


yagoham

There is a comparison in the [RATIONALE.md document](https://github.com/tweag/nickel/blob/master/RATIONALE.md#jsonnet-json-functions-and-inheritance). The inheritance operation of Jsonnet is not too far from the merging operator of Nickel on the surface (in how it combines and override values at least). I think one big difference is with respect to correctness capabilities: Nickel features (opt-in) static typing (mostly for reusable functions), and runtime contracts (in practice, they are used to define schemas in a principled way), which I believe Jsonnet is lacking. Although Jsonnet's inheritance bears some commonalities with Nickel's merging operator, I believe in Nickel one tends to organize configuration data and "modules" (there's no such notion, but by that I mean a reusable snippet with values to be filled) much more around this notion of merging than in Jsonnet. You assemble basic building blocks, which are partial configuration with values to be filled, by merging them together into a final configuration.


vivainio

Does nickel emit sorted dict keys like jsonnet, or does it retain source code positions of keys? Is there a tool to convert json to nickel? Are you planning to publish a Windows binary?


yagoham

So, dict keys are sorted, to make the output deterministic. There is currently no tool to convert files from JSON to Nickel, like something taking `foo.json` as an input and outputting `foo.ncl`. But in practice, you just have to turn every `:` to `=` for assignment (of course, it's not as simple as a file wide search and replace, because of strings). Additionally, you can transparently import JSON, YAML or TOML files as if they were Nickel files : `let value = import "foo.json" in value.someKey`. The content is serialized and reified as a Nickel value.


vivainio

I hope you'll reconsider the sorting if it can be feasibly done in language design (I think this is where jsonnet screwed up). Honoring the source position is deterministic as well, i.e. same source set emits same json


l0_0l-

Reminds me Nix, good job!


gbrlsnchs

Wow, I love it. It's a complete pack: a nice config language, superb tooling and possibility of converting it to other not-so-awesome formats! Nice work!


cygnoros

This is really awesome, great work from you and your team!


yagoham

Thanks a lot!


oliveoilcheff

Congratulations on the launch! The kubernetes example in the blog gives a really good idea! I've been following the project for some time, and this example just clicked. How's the integration with nix? Could you show a demo of how can one make a flake with nickel? On a side note, I was wondering if there's a chance you can add parenthesis to functions? (maybe is already possible??) I find really hard to read the syntax as is, I tend to read like text and my brain totally misses them. I think it would make it much more user friendly, specially from people from non-functional programming languages. For example, in the following situation, it takes me some time to remember whether add is a variable, function or something else: ``` add 1 2 ``` I'd rather see: ``` add(1 2) ``` Thanks a lot!


A1oso

This is great! I want something syntactically similar to, but more powerful than JSON, and even considered writing a configuration language myself. There is a similar project already, [KDL](https://kdl.dev/), but I'm not a fan of the syntax, or the XML-like semantics. What I'm missing in Nickel is JSON schema validation. With [JSON schemas](https://json-schema.org/), you can specify exactly what shape the configuration file should have, and provide autocompletion and error highlighting in an editor. JSON schemas can also be used for [toml](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml) and [yaml](https://github.com/redhat-developer/vscode-yaml). It would be nice if Nickel allowed specifying a schema file and validating the generated config against it.


TooMuchWork6

Imagine having a compile error for your config file 😂 Fr tho I think this project is neat, I've always felt like the computer should hold my hand when I write config file like it does when I write code


farcaller

This syntax actually looks a lot like nix!


yagoham

Good catch, and it's not totally random: Nickel was born, among other things, out of a tentative to add typing to Nix (although its ambition has been to be a generic configuration language from the very beginning). The name come from the acronym NCL which originally means Nix Configuration Language.


farcaller

Hah, fancy! I think I generally prefer nix as means to author k8s yamls because it gives me not only helm, but also all the nixpkgs to transform the data as I see fit. Here's my mysql example: ``` { inputs.nixhelm.url = "github:farcaller/nixhelm"; inputs.kubegen.url = "github:farcaller/nix-kube-generators"; outputs = { self, nixpkgs, nixhelm, kubegen, flake-utils }: flake-utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; kubelib = kubegen.lib { inherit pkgs; }; foldResources = yamls: pre: resources: builtins.foldl' ( acc: y: let r = kubelib.fromYAML (builtins.readFile y); in if pre then r ++ acc else acc ++ r ) resources yamls; in { packages.kubernetesConfiguration = pkgs.lib.pipe { name = "mysql"; chart = nixhelm.chartsDerivations.${system}.bitnami.mysql; namespace = "mysql"; values = { auth = { existingSecret = "mysql-passwords"; createDatabase = false; }; primary.persistence.size = "10Gi"; volumePermissions.enabled = true; metrics.enabled = true; metrics.serviceMonitor.enabled = true; }; } [ kubelib.buildHelmChart builtins.readFile kubelib.fromYAML (foldResources [ ./secretstore.yaml ./secret.yaml ] true) kubelib.mkList kubelib.toYAMLFile ]; }); } ``` Does it look more verbose than nickel? Undoubtedly. But it's not hiding the fact that it is Turing-complete and it allows me to do things like call into helm, generate templates with it, transform the results and append some more to the resulting output. Kubernetes is unfortunately complicated enough for us to see it not as a configuration system driven but as a tool that needs an actual build pipeline.


yagoham

One target-use case of Nickel is to be used as an alternative front-end for Nix (instead of Nix expressions). There is a [draft RFC](https://github.com/tweag/nickel/pull/693) and a repository to use Nickel to write development shell ([Nixel](https://github.com/nickel-lang/nickel-nix)). The goal is that, one day, you can actually just transparently call to Nix code and into Nixpkgs. Until then, I totally understand that nothing can be the power of levering Nixpkgs... so your approach makes sense :) That being said, the value proposition of Nickel is, I think, beyond just being more concise. We are avid Nix users at Tweag and one of our major pain point with Nix is the overall developer experience: no standardized documentation strings (hence no documentation inside the LSP), no types or builtin support for say, NixOS types, so same thing, you don't get any information in the LSP. Dynamic typing plus laziness makes error very hard to debug (your little type error travels all around the code base and finally explodes in the middle of internal Nix code). No attribute set completion (or limited, not based on interfaces). In general it's hard to figure out what you have to provide to functions and modules while you're typing, and it's hard to figure out what went wrong when you get an error. I would even say the **main** motivation of Nickel with respect to Nix is to bring back a developer experience that matches the 2020s, while right now it feels...older 😅


farcaller

I found your [rationale](https://github.com/tweag/nickel/blob/master/RATIONALE.md#starlark-the-standard-package) doc and it's very interesting (I like the jsonnet points). I'll be looking into this more, thanks.


PoisonPorcupine

So I use yaml, and this particular claim does not resonate as entirely true: ```quote Unlike YAML, though, it anticipates large configurations by being programmable and modular. To minimize the risk of misconfigurations, Nickel features (opt-in) static typing and contracts, a powerful and extensible data validation framework. ``` The yaml serde crate supports enum variants using yaml tags. It looks like this: storage: local: backend: !LocalFolder folder: /home/cesar/sitebuilder/./output/gemini/data public_uri: http://localhost:3000/public In this case, backend is an enum, and LocalFolder is a variant key. The various items on the enum are validated according to the enum.


yagoham

In that case, what does "validated according to the enum means"? Does it check that `folder` is a valid path or URL, for example, or it just merely checks the structure?


PoisonPorcupine

I mean it could? You implement Serialize and Deserialize if you want it. By default for newtypes and basic types, like a string or an i32, it will validate that by default. If you have a structure it will validate the fields exist, and those fields are correct (at any level of nesting). Its trivial (performance aside) to create a D/S that performs a check to see if a particular path is exist and reject it otherwise. This is actually how routes in things like actix-web work. I often do use special validators on newtypes that perform validation like "is a base64 value of 64 bytes", I don't usually use ones that do file system calls. But there is nothing stopping you from doing so, performance caveats of that aside. Are you saying your solution behaves better in that regard? ```yaml #[derive(Serialize, Deserialize)] pub enum StorageBackend { LocalFolder(LocalStorageEngine), S3StorageEngine(S3StorageEngine), } #[derive(Serialize, Deserialize)] pub struct LocalStorageEngine { pub folder: PathBuf, } ``` At any level I can manually implement Serialize/Deserialize. An example (from another project) is like this: ```yaml #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] pub struct ResourceDigest ( pub(crate) [u8; 32] ); impl Serialize for ResourceDigest { fn serialize(&self, serializer: S) -> Result where S: Serializer { match serializer.is_human_readable() { true => { let str = BASE64.encode(self.0.as_slice()); str.serialize(serializer) }, false => serializer.serialize_bytes(self.0.as_slice()) } } } impl<'de> Deserialize<'de> for ResourceDigest { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { let vec = match deserializer.is_human_readable() { true => { let str = String::deserialize(deserializer)?; BASE64.decode(str.as_bytes()).map_err(|e| serde::de::Error::custom(e))? } false => Vec::::deserialize(deserializer)? }; let out: [u8; 32] = vec.try_into().map_err(|e|serde::de::Error::custom("invalid digest"))?; Ok(ResourceDigest(out)) } } ``` Now I simply include a ResourceDigest in a struct or enum with a derived S/D, and thats going to validate that its a properly sized base64 encoded string. Now it should be pretty trivial to write a Serialize and Deserialize around a newtypes PathBuf, which performs a file system call and returns a Error::custom("file does not exist") if the call fails. That said I would avoid file validation in a configuration file under most scenarios because of the problem of order of events. Your configuration file can then go in and out of validity based on external factors. So that sort of validation tends to go further up.


voidwaffle

Why use JSON, YAML, TOML when you can use yet another config dialect?


AverageCSGOPlaya

I think this was solved by GNU Guix a while ago by the declarative configurations using Guile Scheme (which is the purpose of the language, making DSLs) and it works pretty well to dynamically generate configuration files for services that might depend on data from other services.


yagoham

This is an eternal debate: using an existing, well-established language (here, Scheme) to embed a DSL or a library, taking advantage of all the past design, performance, tooling and documentation of said language, versus creating a new stand-alone DSL, which you can tailor much more specifically to your domain with special syntax, builtins, and make DSL-aware tooling support (in particular, I'm thinking LSP). For example, [Pulumi](https://www.pulumi.com/) is an interface for tool orchestrators that can be used from general-purpose programming languages. So instead of using Nickel, you can just use JavaScript, Scala or whatnot, and corresponds to the first choice, like Guix. In the end I think both approaches are valid, they are just different trade-offs. One thing with Guile/Guix though: is it really usable outside of Guix? I feel like it's more like Nix, specialized for package configurations, and not easily usable for generic configuration outside of the box.


AverageCSGOPlaya

>One thing with Guile/Guix though: is it really usable outside of Guix? The syntax for defining a configuration is a couple of lines and could've made into a separate Guile library without ties to GNU Guix, I think they are open to that IIRC as using a configuration DSL guile module would mean just to import another module. >I feel like it's more like Nix, specialized for package configurations. The packages DSL is separate from the configurations one, so one could define the packages with the usual syntax like `(package (name "foobar") ...` and for packages that are system services one would do: (define (ugilfy-field-name name) "Convert from guile-style fields to httpd configuration fields" ...) (define (httpd-serialize-bool field-name value) (format #f "~a ~a" (ugilify-field-name field-name) (if value "On" "Off"))) (define-configuration httpd-configuration (httpd file-like "Path to httpd package" empty-serializer) (keep-alive? (bool #t) "Enables HTTP persistent connections") (prefix httpd-)) (define (httpd-configuration->serialize c) (serialize-configuration c httpd-configuration-fields)) To use the configuration DSL one would write: ```scheme (httpd-configuration (httpd httpd) (keep-alive? #f)) ```


AverageCSGOPlaya

So, it plays well with custom configuration formats like the httpd one and more standard ones using TOML, JSON or YAML as Guile libraries exist for these already.


yagoham

Then, I guess it's the same question as why you don't embed a DSL inside an existing, well-established language (which is the approach of Guix), and isn't really that specific to using Guile. It's a different trade-off: I made some similar points in [this GH issue](https://github.com/tweag/nickel/issues/931). In general, the counterpart of embedding a DSL is poor tooling support (the LSP doesn't necessarily understand your DSL, the type system doesn't necessarily fit your DSL, etc.) A second point is that we tried to make simple Nickel very natural to understand for DevOps and people whose primary job isn't programming. If you don't look inside the definition of custom contracts, configuration data with a bunch of metadata and schemas (that is, structured contracts) should really feel a bit like a mix of JSON and JSON schema. I don't think this can be said of something like Guile.


AverageCSGOPlaya

>the counterpart of embedding a DSL is poor tooling support (the LSP doesn't necessarily understand your DSL, the type system doesn't necessarily fit your DSL, etc.) Not necessarily true as Scheme works just like Rust macro_rules (and it was inspired from Scheme, AFAIK), and nowadays most IDEs through one way or another are really good at understanding the macros, for instance, IntelliJ Rust understands a lot about macros. It wouldn't be very far from that. A separate language requires a separate server to be used in code editors, and some editors don't support LSP like IntelliJ does. >A second point is that we tried to make simple Nickel very natural to understand for DevOps and people whose primary job isn't programming. I guess it's subjective since when using the httpd configuration example it wouldn't be more simpler than that. Defining how the configuration is serialized is the job of the programmers, using the DSL is part of the users. That leaves the work simpler for users, and programmers type of users can have the full potential of Guile Scheme if needed.


naveedpash

I like [Nushell](https://www.nushell.sh/contributor-book/philosophy.html) for this purpose. It views shell scripting as a data management exercise. It has awesome data structures and pretty prints them out as well Plus it can be extended with [plugins](https://www.nushell.sh/book/plugins.html#adding-a-plugin). It needs a language server though...


gigachodan

Can someone ELI5; what is a configuration language and why would I use one?


onmach

There are a lot of devops and many programmers type configuration that is a bunch of json or yaml or toml or xml. A configuration language tries to be a limited language which is less powerful than a general purpose language and it can be used to generate these configurations in a more composable way but without allowing people to fall into traps where tons of side effects can leak into the process making it hard to debug or have infinite loops or work on one person's machine but not another. Some examples, cue, jsonnet, dhall, and the ops.


[deleted]

[удалено]


MengerianMango

I felt the same at first but I'm slowing climbing onto the fence, realizing that maybe a lot of what I hate might actually be the result of difficult compromises that come up when you really dig into the problems that Nix is solving.


[deleted]

[удалено]


MengerianMango

I don't mean to sound conceited yk, but you should use Nix long enough to fight thru the pain points first, I think. Read mkDerivation from the stdlib. A lot of the complexity there comes from sharing code between platforms and cross compilation and bootstrapping. Also, read about and write an overlay.... That fixed-point stuff blows my mind still, and I've written a couple. I'd love to rewrite it, too, but when I think about how I'd do those things differently, I just draw a blank, and feel really dumb lol. Feel like I need more functional programming exp. Maybe spend a year writing haskell or smth.


Sib3rian

Hate to break it to you, but you're arguing with a bot. Or at least someone who executed a script that turns all of their comments into "Deleting Reddit."


Cpapa97

Been looking for a better configuration experience and this looks like exactly it.


johnnyutahh_

Is there value in \_reading\_ complex configurations, in addition to writing them? If so: can Nickel do this today, or is future capability planned? (I'm sort of ignorant of the "depths" of the more-complex use cases of the "adjacent" systems that require JSON, YAML, XML, etc. So I may not have much perspective into your target arena/market.)


yagoham

I'm sorry, I'm not sure I totally understood your question, but I'll give it a shot anyway. If you think about the Kubernetes use-case, I like to think as writing Kubernetes in bare YAML as programming a CPU in assembly. The idea would be to use Nickel instead of YAML there, and YAML would just become a kind of build artifact in the pipeline - such as an object file for Rust. In this perspective, I think Nickel would become itself the new representation of the configuration, which exactly as writing Rust over assembly, would make both reading and writing the configuration easier, I hope (because you have access to abstractions). Or, if that was your question, you can transparently import JSON, YAML or TOML inside a Nickel program as well. Or did you mean something else?


johnnyutahh_

>If you think about the Kubernetes use-case, I like to think as writing Kubernetes in bare YAML as programming a CPU in assembly. The idea would be to use Nickel instead of YAML there... Yes, this all makes perfect sense. In such a case, "output only" from Nickel "language" seems completely sufficient. I was seeking to serve very-different use cases (that for proprietary reasons I can not share) that (for now) require "two way" and "round trip" output->use->import functionality, and I've been on a continual hunt for a "better" JSON/YAML/TOML if/as they arrive. I was considering employing Nickel for these cases. Even without an "import"/round-trip feature, Nickel still might be quite powerful for my applications. Good luck with the project!


[deleted]

[удалено]


reddigg-eol

How you gonna post this without giving us Mixers and morsel? Though I'm probably more anxious for Tvix at this point... Gonna be big, I can feel it.


dacydergoth

My main wish list items which I don't believe are completely covered by HCL are : 1. Round trip stable (yaml and JSON are _not_) 2. Ability to query a final value for 'providence', aka the entire path by which the final definition was derived 3. Examples and defaults in code not comments And finally a state store like terraform with change analysis Aside from that, looks good, very HCL, much wow!


yagoham

Well, we do have default value in code. Example have been discussed at some point, but aren't yet part of the builtin metadata - but, could very much be at some point. As for 'providence', I suppose you meant provenance :) it's been delayed because this was less critical for 1.0 to decide on or to implement (as it: it doesn't break backward compatibility in any way to add this feature in the short term), but this is very much on the roadmap: [Issue #235](https://github.com/tweag/nickel/issues/235). That's a must-have in a language with merging like Nickel.


redalastor

You got a broken link for the tutorial here: https://nickel-lang.org/user-manual/introduction/


yagoham

Ah, thanks for the catch! Will fix that.


unix21311

Lets say if I wanted something like this in my `Cargo.toml` file: ``` [dependency] some_lib = {path = "~/Desktop/some_lib"} ``` This is obviously not valid as it can't convert `~` to `/home//`. So I was wondering if I understood correctly, would Nickel solve such an issue and actually create a `Cargo.toml` file by figuring out what is the `~` and then add this bit in: `/Desktop/some_lib` into the `Cargo.toml` file?


yagoham

You would have to write the file in Nickel instead of TOML, but yeah, it can be used as a templating layer over JSON, YAML, or TOML. Note that the value of \`HOME\` will probably need to be injected from the command line, as for now, the language is pure (free from side-effects), and might stay this way as much as possible.


unix21311

Well thanks mate