New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessing values of environment variables #23

Closed
newhoggy opened this Issue Feb 18, 2017 · 19 comments

Comments

Projects
None yet
2 participants
@newhoggy

newhoggy commented Feb 18, 2017

Is there a way to evaluate an environment variable in a dhall expression?

@Gabriel439

This comment has been minimized.

Show comment
Hide comment
@Gabriel439

Gabriel439 Feb 18, 2017

Collaborator

No. Dhall can only import values via file paths or URLs

Collaborator

Gabriel439 commented Feb 18, 2017

No. Dhall can only import values via file paths or URLs

@newhoggy

This comment has been minimized.

Show comment
Hide comment
@newhoggy

newhoggy Feb 18, 2017

Do you see handling of environment variables as something that should be external do Dhall?

newhoggy commented Feb 18, 2017

Do you see handling of environment variables as something that should be external do Dhall?

@Gabriel439

This comment has been minimized.

Show comment
Hide comment
@Gabriel439

Gabriel439 Feb 18, 2017

Collaborator

Actually, I could add support for reading in Dhall expressions via environment variables, using something like this syntax:

{ foo = ${BAR}
}

However, there are two issues with that:

  • I might want to reserve the same syntax for interpolating Text into a string literal, like this:

    let txt = "Hello" in "${txt} world!"
    

    ... and it might be confusing to use the same syntax in two different ways

  • Imported environment variables would have to be valid Dhall expressions, meaning that if you
    wanted to import Text, then you'd have to define the environment variable like this:

    EXAMPLE='"Test"'
    
Collaborator

Gabriel439 commented Feb 18, 2017

Actually, I could add support for reading in Dhall expressions via environment variables, using something like this syntax:

{ foo = ${BAR}
}

However, there are two issues with that:

  • I might want to reserve the same syntax for interpolating Text into a string literal, like this:

    let txt = "Hello" in "${txt} world!"
    

    ... and it might be confusing to use the same syntax in two different ways

  • Imported environment variables would have to be valid Dhall expressions, meaning that if you
    wanted to import Text, then you'd have to define the environment variable like this:

    EXAMPLE='"Test"'
    
@newhoggy

This comment has been minimized.

Show comment
Hide comment
@newhoggy

newhoggy Feb 20, 2017

I can see your point.

What if there was an implicit global let binding that has all the environment variables in them as strings?

For example:

{ foo = ENV.BAR
}

would imply:

let ENV = { BAR = <string-value-of-BAR> } in
{ foo = ENV.BAR
}

newhoggy commented Feb 20, 2017

I can see your point.

What if there was an implicit global let binding that has all the environment variables in them as strings?

For example:

{ foo = ENV.BAR
}

would imply:

let ENV = { BAR = <string-value-of-BAR> } in
{ foo = ENV.BAR
}
@Gabriel439

This comment has been minimized.

Show comment
Hide comment
@Gabriel439

Gabriel439 Feb 20, 2017

Collaborator

What is the motivation for providing support for environment variables, though? The reason I ask is that any program that takes environment variables implicitly could be done by reformulating the program as a function. For example, your code could be written as:

    λ(ENV : { FOO : Text, BAR : Text })
   { foo = ENV.BAR }

... and instead of running:

$ FOO=foo BAR=bar dhall <<< './example'

... you could supply the desired variables as an ordinary function argument when invoking the expression:

$ dhall <<< './example { FOO = "foo", BAR = "bar" }'

... or if you are really constrained to obtain the values from environment variables, you could even do:

$ dhall <<< "./example { FOO = \"${FOO}\", BAR = \"${BAR}\" }"
Collaborator

Gabriel439 commented Feb 20, 2017

What is the motivation for providing support for environment variables, though? The reason I ask is that any program that takes environment variables implicitly could be done by reformulating the program as a function. For example, your code could be written as:

    λ(ENV : { FOO : Text, BAR : Text })
   { foo = ENV.BAR }

... and instead of running:

$ FOO=foo BAR=bar dhall <<< './example'

... you could supply the desired variables as an ordinary function argument when invoking the expression:

$ dhall <<< './example { FOO = "foo", BAR = "bar" }'

... or if you are really constrained to obtain the values from environment variables, you could even do:

$ dhall <<< "./example { FOO = \"${FOO}\", BAR = \"${BAR}\" }"
@newhoggy

This comment has been minimized.

Show comment
Hide comment
@newhoggy

newhoggy Feb 20, 2017

In the last case, it will mostly work except when the environment variable needs to be escaped, which is the tricky bit.

Perhaps all we need is a env-to-dhall command line tool that does all the necessary escaping?

dhall <<< "λ(ENV : $(env-to-dhall)) → { foo = ENV.BAR }"

Or:

dhall <<< "λ(ENV : $(env-to-dhall)) → ./config"

newhoggy commented Feb 20, 2017

In the last case, it will mostly work except when the environment variable needs to be escaped, which is the tricky bit.

Perhaps all we need is a env-to-dhall command line tool that does all the necessary escaping?

dhall <<< "λ(ENV : $(env-to-dhall)) → { foo = ENV.BAR }"

Or:

dhall <<< "λ(ENV : $(env-to-dhall)) → ./config"
@Gabriel439

This comment has been minimized.

Show comment
Hide comment
@Gabriel439

Gabriel439 Feb 21, 2017

Collaborator

Hmmm. I would prefer reading environment variables directly within Dhall as a built-in mechanism rather than provide an env-to-dhall executable

The main issue with env-to-dhall or an Env record in general is that dhall does not allow records to hold fields which are types or kinds. So if one of your environment variables is a type or kind you will get a type error when type-checking the Env record

The second issue (when I thought about this more) is that an env-to-dhall mechanism does not support transitively resolving environment variables. In other words, if an environment variable references another environment variable then Dhall should support that (and do basic cycle checking like it does for files/URLs).

So what I'll probably do is add something like env://FOO to reference the environment variable FOO in Dhall. However, FOO will need to be a valid Dhall expression, meaning that if you want to import a Text string then the contents of FOO need to be quoted.

So in other words, you could do:

$ FOO='"foo"' BAR='1' dhall <<< '{ foo = env://FOO , bar = env://BAR }'
{ bar : Integer, foo : Text }

{ bar = 1, foo = "foo" }

How does that sound?

Collaborator

Gabriel439 commented Feb 21, 2017

Hmmm. I would prefer reading environment variables directly within Dhall as a built-in mechanism rather than provide an env-to-dhall executable

The main issue with env-to-dhall or an Env record in general is that dhall does not allow records to hold fields which are types or kinds. So if one of your environment variables is a type or kind you will get a type error when type-checking the Env record

The second issue (when I thought about this more) is that an env-to-dhall mechanism does not support transitively resolving environment variables. In other words, if an environment variable references another environment variable then Dhall should support that (and do basic cycle checking like it does for files/URLs).

So what I'll probably do is add something like env://FOO to reference the environment variable FOO in Dhall. However, FOO will need to be a valid Dhall expression, meaning that if you want to import a Text string then the contents of FOO need to be quoted.

So in other words, you could do:

$ FOO='"foo"' BAR='1' dhall <<< '{ foo = env://FOO , bar = env://BAR }'
{ bar : Integer, foo : Text }

{ bar = 1, foo = "foo" }

How does that sound?

@newhoggy

This comment has been minimized.

Show comment
Hide comment
@newhoggy

newhoggy Feb 23, 2017

That sounds really good.

Although being able embed variables as string is also useful. I don't mind having to type extra to get it. For example, I'd be happy with env+text://FOO. Even file+text://pubrung.gpg would be helpful too.

newhoggy commented Feb 23, 2017

That sounds really good.

Although being able embed variables as string is also useful. I don't mind having to type extra to get it. For example, I'd be happy with env+text://FOO. Even file+text://pubrung.gpg would be helpful too.

@Gabriel439

This comment has been minimized.

Show comment
Hide comment
@Gabriel439

Gabriel439 Feb 24, 2017

Collaborator

I just realized that env://FOO is a misleading URI since it implies that FOO is the authority as opposed to the path. It seems like env:FOO is the more appropriate URI

I also like the idea of using +text in the scheme to denote that we expect unquoted Text. I'll implement that, too

Collaborator

Gabriel439 commented Feb 24, 2017

I just realized that env://FOO is a misleading URI since it implies that FOO is the authority as opposed to the path. It seems like env:FOO is the more appropriate URI

I also like the idea of using +text in the scheme to denote that we expect unquoted Text. I'll implement that, too

@newhoggy

This comment has been minimized.

Show comment
Hide comment
@newhoggy

newhoggy Feb 24, 2017

Good spot. Thanks!

newhoggy commented Feb 24, 2017

Good spot. Thanks!

@Gabriel439

This comment has been minimized.

Show comment
Hide comment
@Gabriel439

Gabriel439 Mar 4, 2017

Collaborator

Alright, the first part of this is done in 11ceab1 (supporting env:NAME syntax). The env+text and file+text support will come in a subsequent commit

Collaborator

Gabriel439 commented Mar 4, 2017

Alright, the first part of this is done in 11ceab1 (supporting env:NAME syntax). The env+text and file+text support will come in a subsequent commit

@newhoggy

This comment has been minimized.

Show comment
Hide comment
@newhoggy

newhoggy Mar 4, 2017

Looking good!

newhoggy commented Mar 4, 2017

Looking good!

@newhoggy

This comment has been minimized.

Show comment
Hide comment
@newhoggy

newhoggy Mar 5, 2017

I just discovered a case that might need better dhall support:

circle-cli-exe:
↳ ./project.config

Error: Invalid input

project.config:1:17: error: expected: "''",
    "(", "+", "-", "[", "\8704",
    "\955", "\\", "forall", "if",
    "let", "merge", built-in value,
    double, import, integer, label,
    list literal, natural,
    record literal, record type,
    string, union literal,
    union type
{ environment = ~/.circle/project-config/haskell-works.config
                ^

newhoggy commented Mar 5, 2017

I just discovered a case that might need better dhall support:

circle-cli-exe:
↳ ./project.config

Error: Invalid input

project.config:1:17: error: expected: "''",
    "(", "+", "-", "[", "\8704",
    "\955", "\\", "forall", "if",
    "let", "merge", built-in value,
    double, import, integer, label,
    list literal, natural,
    record literal, record type,
    string, union literal,
    union type
{ environment = ~/.circle/project-config/haskell-works.config
                ^
@newhoggy

This comment has been minimized.

Show comment
Hide comment
@newhoggy

newhoggy Mar 5, 2017

At the moment, I'm required to put the absolute path in:

{ environment = /Users/jky/.circle/project-config/haskell-works.config
}

newhoggy commented Mar 5, 2017

At the moment, I'm required to put the absolute path in:

{ environment = /Users/jky/.circle/project-config/haskell-works.config
}
@Gabriel439

This comment has been minimized.

Show comment
Hide comment
@Gabriel439

Gabriel439 Mar 31, 2017

Collaborator

Could I propose an alternative syntax for importing raw Text? I was thinking of adding an as Text suffix to the path in order to import it as a raw Text literal, like this:

{ foo = /foo as Text
, bar = env:HOME as Text
, baz = http://example.com as Text
}

Would that be alright?

Collaborator

Gabriel439 commented Mar 31, 2017

Could I propose an alternative syntax for importing raw Text? I was thinking of adding an as Text suffix to the path in order to import it as a raw Text literal, like this:

{ foo = /foo as Text
, bar = env:HOME as Text
, baz = http://example.com as Text
}

Would that be alright?

Gabriel439 added a commit that referenced this issue Mar 31, 2017

Gabriel439 added a commit that referenced this issue Mar 31, 2017

Add support for importing paths as raw `Text`
Part of #23

You can now add ` as Text` to the end of any path and the raw contents at that
path will be imported as a raw `Text` literal.  For example:

```
$ dhall <<< "http://example.com as Text"
Text

"<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta
 charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html
; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width,
initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        backgro
und-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-famil
y: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n
   }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        paddi
ng: 50px;\n        background-color: #fff;\n        border-radius: 1em;\n    }\n
    a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;
\n    }\n    @media (max-width: 700px) {\n        body {\n            background
-color: #fff;\n        }\n        div {\n            width: auto;\n            m
argin: 0 auto;\n            border-radius: 0;\n            padding: 1em;\n
  }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</
h1>\n    <p>This domain is established to be used for illustrative examples in d
ocuments. You may use this\n    domain in examples without prior coordination or
 asking for permission.</p>\n    <p><a href=\"http://www.iana.org/domains/exampl
e\">More information...</a></p>\n</div>\n</body>\n</html>\n"
```
@Gabriel439

This comment has been minimized.

Show comment
Hide comment
@Gabriel439

Gabriel439 Mar 31, 2017

Collaborator

I put up a PR for the as Text proposal here: #34

Collaborator

Gabriel439 commented Mar 31, 2017

I put up a PR for the as Text proposal here: #34

Gabriel439 added a commit that referenced this issue Mar 31, 2017

Add support for importing paths as raw `Text` (#34)
* Add support for importing paths as raw `Text`

Part of #23

You can now add ` as Text` to the end of any path and the raw contents at that
path will be imported as a raw `Text` literal.  For example:

```
$ dhall <<< "http://example.com as Text"
Text

"<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta
 charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html
; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width,
initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        backgro
und-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-famil
y: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n
   }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        paddi
ng: 50px;\n        background-color: #fff;\n        border-radius: 1em;\n    }\n
    a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;
\n    }\n    @media (max-width: 700px) {\n        body {\n            background
-color: #fff;\n        }\n        div {\n            width: auto;\n            m
argin: 0 auto;\n            border-radius: 0;\n            padding: 1em;\n
  }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</
h1>\n    <p>This domain is established to be used for illustrative examples in d
ocuments. You may use this\n    domain in examples without prior coordination or
 asking for permission.</p>\n    <p><a href=\"http://www.iana.org/domains/exampl
e\">More information...</a></p>\n</div>\n</body>\n</html>\n"
```

* Remove unnecessary space

@Gabriel439 Gabriel439 closed this Mar 31, 2017

@newhoggy

This comment has been minimized.

Show comment
Hide comment
@newhoggy

newhoggy commented Mar 31, 2017

👍

@newhoggy

This comment has been minimized.

Show comment
Hide comment
@newhoggy

newhoggy Mar 31, 2017

Thanks so much!

newhoggy commented Mar 31, 2017

Thanks so much!

@Gabriel439

This comment has been minimized.

Show comment
Hide comment
@Gabriel439

Gabriel439 Mar 31, 2017

Collaborator

You're welcome! :)

Collaborator

Gabriel439 commented Mar 31, 2017

You're welcome! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment