On Tue, Feb 4, 2020 at 10:04 AM Ben Wilson <benwilson...@gmail.com> wrote:

> > The code Function.constant(c) is much more expressive and descriptive
> than fn _ -> c end.
>
> To be clear, if this could work without macros, I'd be inclined to agree,
> although I recognize that there may be some who do not. My issue personally
> is that there simply isn't any function you can write that will behave this
> way, for all values of `c`. You could build `constant` as a macro, but I
> think that ends up killing the whole "name a concept" thing, because really
> the dominant concept at hand ends up being how macros work.
>

I don’t really have a strong opinion on this proposal, but I do think that
this could be done without macros and if naming a concept is important then
it’s worth considering. I do see one problem with `Function.constant/1` in
how it would be applied, because there would potentially need to be some
magic involved (which brings it back to possible macros).

The simplest implementation would be:

def constant(const), do: fn -> const end

That will work well for `Stream.repeatedly/1` as the function parameter is
`/0`, but not so well for `Enum.map/2` as the function parameter is `/1`.
This could be addressed with multiple functions (constant1/1, etc.) or with
an arity parameter (both examples shown below):

def constant(const), do: fn -> const end
def constant1(const), do: fn _ -> const end # OR
def constant(const, arity \\ 0)
def constant(const, 0), do: fn -> const end
def constant(const, 1), do: fn _ -> const end

I’m not sure it would be possible to know, at the call-site, whether you
needed a `/0` or `/1` anonymous function through macros, and I’m not sure
that it would be meaningful to have constant for _larger_ than `/{0,1}`
functions. But I do know that I have occasionally wanted to write:

Enum.map([0, 1, 2], &:padding) # or any other non-function value

and have it act as the correct type of function.

-a


> On Tuesday, February 4, 2020 at 9:39:48 AM UTC-5, Bruce Tate wrote:
>>
>> Thanks for the discussion, all. I enjoy being here.
>>
>> *Summary: I will bow out of this conversation after this one last
>> attempt. Feel free to skip it. *
>>
>> I will say that I would use this function frequently in my teaching and
>> in my day-to-day code if I had it. I think it describes a concept that is
>> well known in math, and useful in any functional language. For example,
>> resetting a counter in an agent or genserver with a similar API. Creating a
>> stream of constants as padding/initialization data of arbitrary length
>> (with take later).
>>
>> > we'll bloat the language.
>>
>> I don't think this is a good argument for foundational concepts. A
>> library that provides names for significant functions in math and
>> programming is important enough.
>>
>> > I’d argue back that this particular pattern, where you want a list of
>> fixed length with the same value, is much better served by
>> `List.duplicate/2`.
>>
>> Maybe. But List.duplicate/2 doesn't really solve the same problem.
>> Stream.repeatedly with Function.constant gives me  padding of an arbitrary
>> length, that I can then later instantiate based on the number of columns
>> that I need. It's a great pattern. It's basically fixed vs variable.
>>
>> > if I know anonymous functions, I know what’s going on.
>>
>> Variables, anonymous functions, and the like are not equivalent. A
>> library function has weight and descriptive ability that writing code just
>> doesn't. I can tell you that `fn(x) -> x end` and `Function.identity` are
>> not remotely equivalent when it comes to scanning code. There's a cost to
>> that much syntax.
>>
>> I'll say one more thing before moving on from this conversation.
>>
>> Naming concepts in code is important. The code Function.constant(c) is
>> much more expressive and descriptive than fn _ -> c end. It gives us a
>> common language across programming languages and theory plus math to
>> express ideas. We in the Elixir community often undersell the idea, and we
>> pay in the idioms that new coders must learn to be successful with our
>> language.
>>
>> *So thanks to all for a great discussion. I do recognize there's no
>> appetite for these ideas in Elixir, so I'll gracefully bow out. *
>>
>> -bt
>>
>>
>>
>> On Tue, Feb 4, 2020 at 8:58 AM Amos King <am...@binarynoggin.com> wrote:
>>
>>> Ben,
>>>
>>> That is how const is used in Haskell. Although without currying I don’t
>>> see how it is useful. I’m waiting to see an example that drives it home. I
>>> agree with Bruce about naming concepts but I don’t see the concept as
>>> useful in Elixir.
>>>
>>> Bruce, do you have a code sample using the idea?
>>>
>>> Amos King
>>> CEO
>>> Binary Noggin
>>>
>>> On Feb 4, 2020, at 07:35, Ben Wilson <benwil...@gmail.com> wrote:
>>>
>>> 
>>> Addendum: I re-read the proposal because the const/1 vs const/2 thing
>>> confused me, and I'm seeing both in play there. The spec is arity 2, the
>>> example right after though is arity 1, and the Enum example is arity 2 but
>>> without a constant value. The Enum example perhaps makes the most sense,
>>> because you could do:
>>>
>>> ```
>>> Enum.map([1,2,3,4], &const(&1, :foo))
>>> ```
>>> which would return `[:foo, :foo, :foo, :foo]` effectively replacing the
>>> contents of the list with all `:foo`. Is that the idea?
>>>
>>> On Tuesday, February 4, 2020 at 8:16:53 AM UTC-5, Ben Wilson wrote:
>>>>
>>>> I agree with Michal. Additionally, I'm not clear how `const/1` could be
>>>> used in Bruce's example at all.
>>>>
>>>> To elaborate,  `fn -> foo() end` and `const(foo())` cannot be
>>>> equivalent when `const/1` is merely a function. This becomes readily
>>>> apparent when `foo()` is side effects or side causes. In the first case,
>>>> `foo()` is never evaluated until the wrapping function is called, in the
>>>> case of `const/1` however the function is evaluated and then its return
>>>> value bound over by a function. Eg: `fn -> DateTime.utc_now() end` will
>>>> always return the current time when evaluated, where as
>>>> `const(DateTime.utc_now())` will evaluate the current time once and then
>>>> always return that same time.
>>>>
>>>> That might sound useful, except that we already can do that by simply
>>>> binding the return value of `DateTime.utc_now()` to a variable and passing
>>>> that variable around. I'm having difficulty coming up with a scenario
>>>> where, instead of simply having the value, I have the value wrapped in an
>>>> anonymous function that I need to call.
>>>>
>>>> Consequently, I struggle to see where `const/1` can actually be used,
>>>> or how it would work. In the example in the initial proposal, there is 
>>>> this:
>>>>
>>>> ```
>>>> Enum.map([0,1,2,3], &Function.const/2)
>>>> ```
>>>>
>>>> As a minor note, presumably that should be `const/1`, right? More
>>>> importantly, what is the return value here? If it's `[0, 1, 2, 3]` then
>>>> `const/1` is equivalent to `identity`. If it's
>>>>
>>>> ```
>>>> [fn -> 1 end, fn -> 2 end, fn -> 3 end, fn -> 4 end]
>>>> ```
>>>>
>>>> then a simple list of integers seems universally more useful.
>>>>
>>>> On Tuesday, February 4, 2020 at 5:03:39 AM UTC-5, Michał Muskała wrote:
>>>>>
>>>>> I’d argue back that this particular pattern, where you want a list of
>>>>> fixed length with the same value, is much better served by
>>>>> `List.duplicate/2`.
>>>>>
>>>>>
>>>>>
>>>>> I think in general, higher order combinator functions like identity,
>>>>> const, flip, and friends are usually used to facilitate the point-free
>>>>> style of programming in languages like Haskell. And in general point-free
>>>>> style usually does not lead to the most readable code.
>>>>>
>>>>>
>>>>>
>>>>> Again, referring to the example provided, if I know anonymous
>>>>> functions, I know what’s going on. When using `Funcion.const`, I have to
>>>>> understand that concept as well. There’s one extra thing to learn.
>>>>>
>>>>>
>>>>>
>>>>> Michał.
>>>>>
>>>>>
>>>>>
>>>>> *From: *"elixir-l...@googlegroups.com" <elixir-l...@googlegroups.com>
>>>>> on behalf of Bruce Tate <br...@grox.io>
>>>>> *Reply to: *"elixir-l...@googlegroups.com" <
>>>>> elixir-l...@googlegroups.com>
>>>>> *Date: *Monday, 3 February 2020 at 11:47
>>>>> *To: *"elixir-l...@googlegroups.com" <elixir-l...@googlegroups.com>
>>>>> *Subject: *Re: [elixir-core:9353] [Proposal] Add Function.const/2
>>>>>
>>>>>
>>>>>
>>>>> My counterpoint is this. Any time you can name a concept that makes it
>>>>> easier to see what's going on, it's important.
>>>>>
>>>>>
>>>>>
>>>>> Examples:
>>>>>
>>>>> * Create back padding of four blank table cells
>>>>>
>>>>> * use with Stream.repeatedly and take, for example, to initialize a
>>>>> data structure for OTP.
>>>>>
>>>>>
>>>>>
>>>>> I do these two things with pretty good frequency because I build
>>>>> responsive layouts often needing tabular structure, but without HTML
>>>>> tables.
>>>>>
>>>>>
>>>>>
>>>>> Say you are laying out tables that are responsive but without HTML
>>>>> tables. You
>>>>>
>>>>> d want to add padding to the end of uneven rows. To create the padding
>>>>> you'd do
>>>>>
>>>>>
>>>>>
>>>>> Stream.repeatedly( fn -> :padding end) |> Enum.take(4)
>>>>>
>>>>>
>>>>>
>>>>> where :padding is the constant padding you want. This pattern comes up
>>>>> with some regularity in my user interfaces. It doesn't hurt anything, and
>>>>> it would be a great addition to the function module.
>>>>>
>>>>>
>>>>>
>>>>> I like this proposal. This is exactly the kind of function you'd
>>>>> expect to see in the module.
>>>>>
>>>>>
>>>>>
>>>>> +1 from me.
>>>>>
>>>>>
>>>>>
>>>>> -bt
>>>>>
>>>>>
>>>>>
>>>>> On Sun, Feb 2, 2020 at 2:42 PM Jesse Claven <jesse...@gmail.com>
>>>>> wrote:
>>>>>
>>>>> That all makes sense! I would say that in Elm it's used somewhat
>>>>> frequently. I don't have access to the previous code that I worked on
>>>>> (changed jobs), so unfortunately I'm unable to grep for `always` to find
>>>>> some good examples.
>>>>>
>>>>>
>>>>>
>>>>> In the codebase at my new job, there's a couple of places where `fn _
>>>>> -> something` is (my original example in this thread). It's basically for
>>>>> anywhere you'd want to ignore some value, and always return something 
>>>>> else.
>>>>> I tried searching through GitHub for that code sample but the search
>>>>> functionality was a little subpar.
>>>>>
>>>>>
>>>>>
>>>>> I understand about keeping the stdlib small, but for a relatively
>>>>> small function, and one that's considered "table stakes" in most FP
>>>>> languages, perhaps it would be a good fit?
>>>>>
>>>>>
>>>>> On Thursday, 30 January 2020 11:20:58 UTC, Wiebe-Marten Wijnja wrote:
>>>>>
>>>>> The reason `Function.identity/1` was added after it was requested many
>>>>> times previously, was that at some point everyone agreed that it would
>>>>> improve Elixir's documentation, because it is easier to search for than
>>>>> `&(&1)`.
>>>>>
>>>>> The `const` pattern is much less wide-spread. In e.g. Haskell it sees
>>>>> some use in places where it is the single (or at least by far the 
>>>>> simplest)
>>>>> way to make things typecheck in a pure functional environment.
>>>>>
>>>>> In Elixir, I suspect that it would be used much less commonly. The
>>>>> fact that our functions contain statements that are executed from top to
>>>>> bottom and rebindable variable names means that we are even less likely to
>>>>> use it anywhere.
>>>>>
>>>>> As such, I don't think `const` is a function that is important enough
>>>>> to include in the standard library.
>>>>>
>>>>>
>>>>>
>>>>> Of course, I'm very much open to evidence of the contrary ^_^. Do you
>>>>> have any example code of where you'd see `const` being useful?
>>>>>
>>>>>
>>>>>
>>>>> ~Marten/Qqwy
>>>>>
>>>>> On 30-01-2020 10:24, Jesse Claven wrote:
>>>>>
>>>>> Hey Amos,
>>>>>
>>>>>
>>>>>
>>>>> Ah that's right. Every now and then I'm reminded that Elixir doesn't
>>>>> support currying when I try to do something haha Your suggestion makes
>>>>> sense.
>>>>>
>>>>>
>>>>>
>>>>> Would there be any downsides to having it, even if it isn't the most
>>>>> incredible function? Again to call on the `Function.identity/1`, and it's
>>>>> discussion, it's useful when it's useful for concise and semantic code.
>>>>>
>>>>>
>>>>> On Wednesday, 29 January 2020 22:43:51 UTC, Amos King - Binary Noggin
>>>>> wrote:
>>>>>
>>>>> Jesse,
>>>>>
>>>>>
>>>>>
>>>>> I see where you are going, but Elixir doesn't have currying. For
>>>>> instance, the last example you gave will return an error.
>>>>>
>>>>>
>>>>>
>>>>> You could make it work by changing it a bit.
>>>>>
>>>>>
>>>>>
>>>>> `@spec const(a) :: fn(any() -> a) when a: var`
>>>>>
>>>>>
>>>>>
>>>>> So, const would return an fn instead of taking two arguments. I don't
>>>>> know how useful that would be in the long run. I know it is common in
>>>>> function programming, but I don't see it being extremely helpful in 
>>>>> Elixir.
>>>>>
>>>>>
>>>>>
>>>>> I'm ready to be convinced.
>>>>>
>>>>>
>>>>>
>>>>> Cheers,
>>>>>
>>>>>
>>>>>
>>>>> Amos King
>>>>>
>>>>> CEO
>>>>>
>>>>> Binary Noggin
>>>>>
>>>>> http://binarynoggin.com #business
>>>>>
>>>>> https://elixiroutlaws.com #elixir podcast
>>>>>
>>>>> http://thisagilelife.com #podcast
>>>>>
>>>>> =======================================================
>>>>>
>>>>> I welcome VSRE emails. Learn more at http://vsre.info/
>>>>>
>>>>> =======================================================
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Wed, Jan 29, 2020 at 4:01 PM Jesse Claven <jesse...@gmail.com>
>>>>> wrote:
>>>>>
>>>>> Hey everyone!
>>>>>
>>>>> I propose adding `Function.const/2` as a function which for argument
>>>>> `x`, would always return `x`.
>>>>>
>>>>> ```
>>>>> @spec const(any(), any()) :: any()
>>>>> def const(_original_value, new_value), do: new_value
>>>>> ```
>>>>>
>>>>> This is somewhat similar to the new `Function.identity/1` in that it
>>>>> may seem like we've easily lived without it, but it does afford some more
>>>>> concise/semantic ways to represent a common pattern.
>>>>>
>>>>> ```
>>>>> fn _ -> something_else() end
>>>>> ```
>>>>>
>>>>> This would become:
>>>>>
>>>>> ```
>>>>> const(something_else())
>>>>> ```
>>>>>
>>>>> ```
>>>>> Enum.map([0,1,2,3], &Function.const/2)
>>>>> ```
>>>>>
>>>>> I'm new to Elixir, so I'm not sure of the weight that the name `const`
>>>>> would carry, so there could be a more acceptable name.
>>>>>
>>>>> If accepted, I'd be happy to create a PR!
>>>>>
>>>>> Equivalents in other languages:
>>>>>
>>>>> - Haskell:
>>>>> https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Function.html#v:const
>>>>> - PureScript:
>>>>> https://pursuit.purescript.org/packages/purescript-const/4.1.0/docs/Data.Const
>>>>> - Elm:
>>>>> https://package.elm-lang.org/packages/elm/core/latest/Basics#always
>>>>> - Scala:
>>>>> https://www.scala-lang.org/api/current/scala/Function$.html#const[T,U](x:T)(y:U):T
>>>>>
>>>>> - Idris:
>>>>> https://www.idris-lang.org/docs/current/prelude_doc/docs/Prelude.Basics.html#Prelude.Basics.const
>>>>>
>>>>>
>>>>>
>>>>> Thanks for your time.
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "elixir-lang-core" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to elixir-l...@googlegroups.com.
>>>>> To view this discussion on the web visit
>>>>> https://groups.google.com/d/msgid/elixir-lang-core/576949a3-93e2-4117-b1f1-ab4621f10e88%40googlegroups.com
>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/576949a3-93e2-4117-b1f1-ab4621f10e88%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>> .
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "elixir-lang-core" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to elixir-l...@googlegroups.com.
>>>>> To view this discussion on the web visit
>>>>> https://groups.google.com/d/msgid/elixir-lang-core/f8b6009d-e21a-434a-96e0-e2c6ae3c1a0e%40googlegroups.com
>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/f8b6009d-e21a-434a-96e0-e2c6ae3c1a0e%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>> .
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "elixir-lang-core" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to elixir-l...@googlegroups.com.
>>>>> To view this discussion on the web visit
>>>>> https://groups.google.com/d/msgid/elixir-lang-core/294d4f77-6b91-4316-a152-0c209fad12db%40googlegroups.com
>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/294d4f77-6b91-4316-a152-0c209fad12db%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>> .
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>>
>>>>>
>>>>>
>>>>> Regards,
>>>>>
>>>>> Bruce Tate
>>>>>
>>>>> CEO
>>>>>
>>>>>
>>>>>
>>>>> [image: Image removed by sender.]
>>>>>
>>>>>
>>>>>
>>>>> Groxio, LLC.
>>>>>
>>>>> 512.799.9366
>>>>>
>>>>> br...@grox.io
>>>>>
>>>>> grox.io
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "elixir-lang-core" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to elixir-l...@googlegroups.com.
>>>>> To view this discussion on the web visit
>>>>> https://groups.google.com/d/msgid/elixir-lang-core/CAFXvW-6%3DfheYjjyQ7xiWYkP0B0t%2BfoGae9OGtkDDSvSpD4s_Sg%40mail.gmail.com
>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/CAFXvW-6%3DfheYjjyQ7xiWYkP0B0t%2BfoGae9OGtkDDSvSpD4s_Sg%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>>>> .
>>>>>
>>>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "elixir-lang-core" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to elixir-l...@googlegroups.com.
>>> To view this discussion on the web visit
>>> https://groups.google.com/d/msgid/elixir-lang-core/1a49eabe-6509-41c7-b425-21e207737472%40googlegroups.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/1a49eabe-6509-41c7-b425-21e207737472%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "elixir-lang-core" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to elixir-l...@googlegroups.com.
>>> To view this discussion on the web visit
>>> https://groups.google.com/d/msgid/elixir-lang-core/05581EC8-0AF0-4301-8B45-4F0B78544B2D%40binarynoggin.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/05581EC8-0AF0-4301-8B45-4F0B78544B2D%40binarynoggin.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>>
>>
>> --
>>
>> Regards,
>> Bruce Tate
>> CEO
>>
>>
>> <https://bowtie.mailbutler.io/tracking/hit/f8218219-d2a8-4de4-9fef-1cdde6e723f6/c7c97460-016e-45fb-a4ab-0a70318c7b97>
>>
>> Groxio, LLC.
>> 512.799.9366
>> br...@grox.io
>> grox.io
>>
> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to elixir-lang-core+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/89aa185d-368d-4c95-ac41-d5e91f343b7b%40googlegroups.com
> <https://groups.google.com/d/msgid/elixir-lang-core/89aa185d-368d-4c95-ac41-d5e91f343b7b%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>


-- 
Austin Ziegler • halosta...@gmail.com • aus...@halostatue.ca
http://www.halostatue.ca/http://twitter.com/halostatue

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elixir-lang-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAJ4ekQuQKUdJfBPemtqVvY%2BHHP7HHsvwx6bpGYBTu1WuM6zxbw%40mail.gmail.com.

Reply via email to