# Using \> and \>\> as kwargs

**URL:** <https://discourse.julialang.org/t/using-and-as-kwargs/14363>\
**Category:** General Usage\
**Created:** [August 31, 2018, 1:34pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363 "2018-08-31T13:34:11Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [August 31, 2018, 1:34pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/1 "2018-08-31T13:34:11Z")

</div>

Hi,  
I would like to be able to use the `>` and `>>` characters as valid kwarg names. Example

```julia
julia> grd2xyz(G, >="lixo.xyz")
ERROR: syntax: ">=" is not a unary operator

```

The reason why it fails seems understandable, but I managed to make it work with the pipe operator.

```julia
julia> grd2xyz(G, |>="lixo.xyz")

```

Let me say that the parsing of the above is done by this line

```julia
if (haskey(d, :|>))	cmd = string(cmd, " > ", d[:|>])	end

```

So, neither `>` nor `|>` are unary operators but I can use `|>` as kwarg name but not `>`.  
All would be good if I didn’t want to implement also the `>>` kwarg for the shell append to file operator. And here nothing that I tried works. `|>>` seemed the logical one, but again

```julia
julia> grd2xyz(G, |>>="lixo.xyz")
ERROR: syntax: "|>" is not a unary operator

```

Ant deep trick to accomplish these?  
Thanks.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 31, 2018, 1:36pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/2 "2018-08-31T13:36:20Z")

</div>

Use some space:

```julia
julia> f(x; > = 1) = >
f (generic function with 1 method)

julia> f(1, > = 2)
2

```

Just be aware that you can’t use the `>` operator in the function `f`, which seems like a problem to me (unless you go the kwargs Dict route, but that’s more suited for handling an unknown number of keywords which may contain some you don’t want to/can’t handle).

The reason your original didn’t work is because of [operator precedence](https://docs.julialang.org/en/stable/manual/mathematical-operations/#Operator-Precedence-and-Associativity-1) - julia tries to evaluate the expression `>="lixo.xyz"` during which it doesn’t find a second argument to `>=`, since that’s a binary operator. Assignments have the lowest precedence, which is why you have to write it this way with the space.

In general though, it’s adviced not to do that. Is there a special reason you want to have that character as an argument?

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [August 31, 2018, 2:02pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/3 "2018-08-31T14:02:17Z")

</div>

Thanks, and yes, I see the risk of it.  
The reason why I want to have those characters is be cause they exactly match what one would do in the shell. To explain better, on the shell this (GMT) command

```julia
grd2xyz G > lixo.xyz

```

Takes a grid (`G`) and converts it to a Mx3 file with `x,y,z` values. The closest I can get from the GMT Julia wrapper is to do

```julia
grd2xyz(G, > ="lixo.xyz")

```

Sure that can impose another syntax like

```julia
grd2xyz(G, redirect="lixo.xyz")

```

but then for appending to a previously existing file I would need something like

```julia
grd2xyz(G, redirect_append="lixo.xyz")

```

… humm, but now that I’m looking at it maybe it doesn’t look so bad.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 31, 2018, 2:05pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/4 "2018-08-31T14:05:33Z")

</div>

I definitely think having clear names for keyword arguments is more julian - after all, if someone else is going to use that function at some point, they are bound to fall into the same pitfall you did with the operator precedence. Moreover, having a clear to read name helps reduce ambiguity - someone not used to Bash or some other Shell might not know about output redirection using `>` there. For them, having `>` as a keyword is surely going to feel alien and unintuitive.

You could also take a look at how `open` does it with it’s `mode` argument. As far as I know, having a mode is pretty much universal when it comes to IO (think C).

```julia
help?> open
# <snip>
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  open(filename::AbstractString, [mode::AbstractString]) -> IOStream

  Alternate syntax for open, where a string-based mode specifier is used instead of the five booleans. The values of mode correspond to those from fopen(3) or Perl open, and are
  equivalent to setting the following boolean groups:

Mode Description Keywords
–––– ––––––––––––––––––––––––––––– ––––––––––––––––––––––––––––
r read none
w write, create, truncate write = true
a write, create, append append = true
r+ read, write read = true, write = true
w+ read, write, create, truncate truncate = true, read = true
a+ read, write, create, append append = true, read = true

# snip

```

Or maybe even check out the `do` syntax?

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [August 31, 2018, 2:19pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/5 "2018-08-31T14:19:05Z")

</div>

Thanks again, but the opening mode is not really an alternative here. The `>` or `redirect` serves as an alternative output (to a disk file) instead of returning the result of the operation into a julia variable. e.g

```julia
D = grd2xyz(G);

```

will return a Mx3 matrix (wrapped into a [GMTdataset](https://genericmappingtools.github.io/GMT.jl/latest/types/)) into the `D` Julia variable.

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [August 31, 2018, 2:21pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/6 "2018-08-31T14:21:12Z")

</div>

Use a macro  
Or possibly better yet, a string macros for your whole expression.  
String macros are designed for implementinv DSLs.

And unlike macros are not tied to only work with things that parse

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 31, 2018, 2:21pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/7 "2018-08-31T14:21:30Z")

</div>

You can return & write to file independently - a `mode` keyword with default being `return_only` or something like that would accomplish that. Different modes can, in addition to the return, also write to the file specified. I just gave `open` as an example since that has a `mode` keyword used to distinguish between behaviour.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [August 31, 2018, 2:33pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/8 "2018-08-31T14:33:36Z")

</div>

Thanks but … other than I’m not in metaprograming yet, it’s a bit late for changing things now as I already wrote [quite a few code](https://github.com/GenericMappingTools/GMT.jl/tree/master/src) now

---

<div class="post-metadata">

**Author:** ![favba](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/favba/32/2735_2.png) [@favba](https://discourse.julialang.org/u/favba)\
**Post date:** [August 31, 2018, 2:44pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/9 "2018-08-31T14:44:14Z")

</div>

That is actually a good starting point for using macros. Since you already coded most of the functionality, now you can just create convenient macros that will rewritte expressions that resembles GMT syntax to your function calls already written.

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [August 31, 2018, 2:49pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/10 "2018-08-31T14:49:18Z")

</div>

It is never to late to rewrite code. 😛  
(It is why I prefer coding to wood working, or sewing, or welding or …)

Anyway, for next time you want to do weird syntax.  
Here is how to use a cmd macro (string macros are basically the same)  
to put a DSL into julia.

Lets say you have a function, that is fairly standard julia code.

```julia-auto
function grd2xyz(G, mode=nothing, file=nothing)
	F = G*G # or what wever operation you need to do
	if mode == ">>"
	   println("appending $F to $file")
	elseif mode == ">"
	   println("overwriting $F to $file")
	end
	return F
end

```

Here is the macro to wrap a DSL around that function

```julia-auto
macro grd2xyz_cmd(str)
	tofile_match = match(r"(.*?)\s*(>+)\s*(.*)", str)
	if tofile_match!==nothing
		mainarg, modearg, filearg = tofile_match.captures
		filearg = Meta.parse(filearg)
	else
		mainarg = str;
		modearg = nothing
		filearg = nothing
	end
	mainarg = Meta.parse(mainarg)
	:(grd2xyz($mainarg, $modearg, $filearg))
end

```

## Demo

```julia-auto
julia> grd2xyz`10`
100

julia> grd2xyz`10 >> "a.txt"`
appending 100 to a.txt
100

julia> grd2xyz`10 > "a.txt"`
overwriting 100 to a.txt
100

julia> b = "b.txt"
"b.txt"

julia> grd2xyz`10 > b` # look variables work
overwriting 100 to b.txt
100

```

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [August 31, 2018, 2:53pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/11 "2018-08-31T14:53:46Z")

</div>

I may be wrong ofc, but the issue is that I already coded all the machinery needed to rewrite the expressions into what the syntax that GMT lib expects. And it’s not all strings. For example both of this are valid Julia syntax (to define a bounding box)  
` limits="0/10/0/10"` or `limits=[0 10 0 10]` or `limits=G` where `G` is a grid and extra code will take charge to extract the BB from the grid’s header.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [August 31, 2018, 3:06pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/12 "2018-08-31T15:06:40Z")

</div>

> [@oxinabox](#):
>
> It is never to late to rewrite code. 😛

Sure (when one get tired of old bugs and need new ones 😉)  
I’ll keep a trace on this for next time I need something of this kind. That’s the beauty of this forum.  
BTW here is the [grd2xyz](https://github.com/GenericMappingTools/GMT.jl/blob/master/src/grd2xyz.jl). A relatively small one but there are others with tons of options.

---

<div class="post-metadata">

**Author:** ![jandehaan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jandehaan/32/6805_2.png) [@jandehaan](https://discourse.julialang.org/u/jandehaan)\
**Post date:** [August 31, 2018, 6:10pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/13 "2018-08-31T18:10:47Z")

</div>

> [@joa-quim](#):
>
> The reason why I want to have those characters is be cause they exactly match what one would do in the shell. To explain better, on the shell this (GMT) command

I scanned the GMT and GMT.jl projects. Powerful stuff! Thank you for developing a Julia API for GMT.

According to the documentation you support “Monolitic” and “By Module” modes. Your original question was about

```julia
julia> grd2xyz(G, >="lixo.xyz")

```

That seems to be “By Module” mode and for that you already translate one letter GMT options to more readable Julia keyword arguments. In that context I see nothing wrong with translating the ‘\>’ operator to keyword argument `redirect=`.

With respect to your “Monolitic” mode, consider adding (as a future enhancement) a string macro (or command macro) that translates any GMT shell command to the API you already have.  
For example `macro GMT_str` could translate

```julia
GMT" grd2xyz G > lixo.xyz "

```

to

```julia
grd2xyz(G, redirect="lixo.xyz")

```

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [August 31, 2018, 8:30pm UTC](https://discourse.julialang.org/t/using-and-as-kwargs/14363/14 "2018-08-31T20:30:28Z")

</div>

> [@jandehaan](#):
>
> keyword argument `redirect=` .

I ended up with `write=...` and `write_append` because `redirect` calls to the shell `>` concept and as mentioned above, there are people that don’t know much about that.

As for the “Monolithic” mode, well that’s how things work. I mean, that’s what the GMT lib actually understands. The “By modules” was a large effort to come up with something less cryptic but under the hood all is translated to the “Monolithic” way, which has tight rules on the order of (variable) input data. It’s because of these tight rules that I’m afraid a macro language would be hard to implement. But who knows.
