# Macro for plotting simple curves

**URL:** <https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623>\
**Category:** General Usage\
**Tags:** question, plotting\
**Created:** [October 2, 2020, 12:36am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623 "2020-10-02T00:36:27Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [October 2, 2020, 12:36am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/1 "2020-10-02T00:36:27Z")

</div>

Do any of the plotting packages have a macro for plotting simple curves? I’m looking for something like this:

```julia
# plot the curve from x=-10 to x=10
@curve(x^3 - 6x^2 + 4x + 12, -10, 10)

```

Basically, I’m looking for something as quick and easy to use as going to Wolfram Alpha and typing this in:

```julia
plot x^3 - 6x^2 + 4x + 12

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 2, 2020, 1:05am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/2 "2020-10-02T01:05:51Z")

</div>

Probably not, because we can do this:

```julia
plot([x^3 - 6x^2 + 4x + 12 for x in -10:0.1:10])

```

which doesn’t have many more characters than the macro example. (But you know that already 🙂 )

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [October 2, 2020, 1:34am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/3 "2020-10-02T01:34:45Z")

</div>

Unfortunately that doesn’t plot the right thing. When you only provide one vector, `y`, with length `N`, the `plot` function plots that `y` vector versus `x=1:N`. So the output of

```julia
plot([x^3 - 6x^2 + 4x + 12 for x in -10:0.1:10]; legend=false)

```

is this:

 ![test](https://global.discourse-cdn.com/julialang/original/3X/6/4/640305c2e175ac22fa64c9f8fc542c9eea84f47f.png)

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 2, 2020, 1:37am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/4 "2020-10-02T01:37:16Z")

</div>

True, perhaps this is most character-economic version?

```julia
 x=-10:0.1:10; plot(x,@. x^3 - 6x^2 + 4x + 12)

```

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [October 2, 2020, 1:40am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/5 "2020-10-02T01:40:02Z")

</div>

Not bad! Though for some reason I find `10:0.1:10` hard to type. 😝

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [October 2, 2020, 1:42am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/6 "2020-10-02T01:42:58Z")

</div>

Fwiw I use Desmos for this kind of thing and like it.

---

<div class="post-metadata">

**Author:** ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)\
**Post date:** [October 2, 2020, 1:44am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/7 "2020-10-02T01:44:07Z")

</div>

This is an exercise in my macro tutorials 🙂

An example solution with no error handling might be:

```julia
import Plots

to_string(e) = String(Symbol(e))

macro curve(e, from, to)
    quote
        Plots.plot(
            range($(esc(from)), $(esc(to)), length = 512),
            $(
                Expr(
                    :->,
                    esc(:x),
                    esc(e),
                )
            ),
            ylabel = $(to_string(e)),
        )
    end
end

@curve(x^3 - 6x^2 + 4x + 12, -10, 10)

```

A more exciting variant is to analyze the expression so that an expression in only `x` is a 2D plot and an expression in `x` and `y` is a 3D plot.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [October 2, 2020, 2:07am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/8 "2020-10-02T02:07:54Z")

</div>

With `Plots`:

```julia
julia> plot(f::F, rang) where {F<:Function} = scatter([x for x in rang], [f(x) for x in rang])
plot (generic function with 1 method)

julia> plot(x -> -x^2 + x - 1.0, -1:0.1:1)

```

![image](https://global.discourse-cdn.com/julialang/original/3X/a/1/a1e17b2b4016abbe7beed0ea9c88ff270705407c.png)  
Edit: Sorry, forgot to subtype.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [October 2, 2020, 2:53am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/9 "2020-10-02T02:53:51Z")

</div>

Now what would be really great is if Makie or Plots had a `@curve` macro _and_ some logic that determines a good scale for the axes like Wolfram Alpha does. Then I could just type this:

```julia
@curve(x^3 - 6x^2 + 4x + 12)

```

EDIT:

I think I could even get away with typing it like this:

```julia
@curve x^3 - 6x^2 + 4x + 12

```

EDIT #2:

Though the parsing might be too fragile without the parentheses. Note the difference between these two expressions:

```julia
julia> Meta.show_sexpr(:(@curve x^3 - 6x^2 + 4x + 12))
(:macrocall, Symbol("@curve"), :(#= REPL[30]:1 =#), (:call, :+, (:call, :-, (:call, :^, :x, 3), (:call, :*, 6, (:call, :^, :x, 2))), (:call, :*, 4, :x), 12))

julia> Meta.show_sexpr(:(@curve x^3 -6x^2 + 4x + 12))
(:macrocall, Symbol("@curve"), :(#= REPL[31]:1 =#), (:call, :^, :x, 3), (:call, :+, (:call, :*, -6, (:call, :^, :x, 2)), (:call, :*, 4, :x), 12))

```

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [October 2, 2020, 3:12am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/10 "2020-10-02T03:12:43Z")

</div>

There are some really cool things logic wise that you could do to find scales for plotting. One potentially interesting option would be to use autodiff and root-finding to make sure that all zeros and turning points were included in the plot.

---

<div class="post-metadata">

**Author:** ![briochemc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/briochemc/32/4209_2.png) [@briochemc](https://discourse.julialang.org/u/briochemc)\
**Post date:** [October 2, 2020, 4:55am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/11 "2020-10-02T04:55:50Z")

</div>

Why not just

```julia
using Plots
plot(x -> x^3 - 6x^2 + 4x + 12, xlim=(-10,10))

```

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [October 2, 2020, 5:08am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/12 "2020-10-02T05:08:51Z")

</div>

Hey, that’s pretty good! I’m really not very proficient with plotting in Julia, so I either forgot about that plot method or I never knew it existed… 🙂

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [October 2, 2020, 5:34am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/13 "2020-10-02T05:34:40Z")

</div>

This seems to work too:

```julia
plot([x -> x^3 - 6x^2 + 4x + 12],-10,10)

```

---

<div class="post-metadata">

**Author:** ![briochemc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/briochemc/32/4209_2.png) [@briochemc](https://discourse.julialang.org/u/briochemc)\
**Post date:** [October 2, 2020, 5:38am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/14 "2020-10-02T05:38:24Z")

</div>

Ah yes! Don’t even need the square brackets actually:

```julia
plot(x -> x^3 - 6x^2 + 4x + 12, -10, 10)

```

@CameronBieganek This is really close to what you wanted, just change `@curves` into `plot`, and add the `x ->` to make it explicit that it is a function of `x`.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [October 2, 2020, 6:07am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/15 "2020-10-02T06:07:33Z")

</div>

Take that Wolfram! 😂

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [October 2, 2020, 6:35am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/16 "2020-10-02T06:35:33Z")

</div>

If you omit the bounds, Plots will choose some (I think just -5 to 5):

```julia
plot(x -> x^3 - 2x^2 + 3x - 1)

```

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [October 2, 2020, 2:53pm UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/17 "2020-10-02T14:53:48Z")

</div>

Awesome! So I’ll start with

```julia
plot(x -> x^3 - 2x^2 + 3x - 1)

```

and then refine the window size as needed with

```julia
plot(x -> x^3 - 2x^2 + 3x - 1, -10, 10)

```

---

<div class="post-metadata">

**Author:** ![mefob](https://avatars.discourse-cdn.com/v4/letter/m/ea5d25/32.png) [@mefob](https://discourse.julialang.org/u/mefob)\
**Post date:** [October 2, 2020, 5:47pm UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/18 "2020-10-02T17:47:57Z")

</div>

The two gnuplot packages `Gnuplot.jl` and `Gaston.jl` also support direct plotting of functions.  
One advantage is that they load very quickly.

> **[GitHub - gcalderone/Gnuplot.jl: Julia interface to gnuplot](https://github.com/gcalderone/Gnuplot.jl)**
>
> Julia interface to gnuplot. Contribute to gcalderone/Gnuplot.jl development by creating an account on GitHub.

```julia
x = 1.:20
@gp x x.^2 "with lines title 'Parabola'"https://github.com/mbaz/Gaston.jl
save(term="pngcairo size 480,360", output="examples/ex1.png")
save("parabola.gp") # => save a script file with both data and command to re-create the plot.

```

> **[GitHub - mbaz/Gaston.jl: A julia front-end for gnuplot.](https://github.com/mbaz/Gaston.jl)**
>
> A julia front-end for gnuplot. Contribute to mbaz/Gaston.jl development by creating an account on GitHub.

```julia
using Gaston, SpecialFunctions
x = y = 0:0.075:10
surf(x, y, (x,y) -> besselj0(y)*x^2, with = "pm3d",
     Axes(view = (45, 45),
          pm3d = "lighting primary 0.5 specular 0.4",
          key = :off)
     )

```

![download](https://global.discourse-cdn.com/julialang/original/3X/0/f/0f5d1af702bb79007b50f7da222e81e0cce78877.png)

---

<div class="post-metadata">

**Author:** ![mbaz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbaz/32/17295_2.png) [@mbaz](https://discourse.julialang.org/u/mbaz)\
**Post date:** [October 2, 2020, 6:33pm UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/19 "2020-10-02T18:33:09Z")

</div>

> [@mefob](#):
>
> The two gnuplot packages `Gnuplot.jl` and `Gaston.jl` also support direct plotting of functions.

Correct – and the syntax `plot(f::Function, xmin, xmax; samples=100)` will be available in the next release of `Gaston.jl`, with automatic calculation of number of samples (if I can get it to work). See [Add `plot(::Function, x1::Real, x2::Real; samples::Real = 100)` syntax · Issue #137 · mbaz/Gaston.jl · GitHub](https://github.com/mbaz/Gaston.jl/issues/137)

---

<div class="post-metadata">

**Author:** ![Norbert-droid](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/norbert-droid/32/20364_2.png) [@Norbert-droid](https://discourse.julialang.org/u/Norbert-droid)\
**Post date:** [January 8, 2021, 1:20am UTC](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623/20 "2021-01-08T01:20:42Z")

</div>

What is the link to your tutorial?

[Next page](https://discourse.julialang.org/t/macro-for-plotting-simple-curves/47623.md?page=2)
