1. imp, discussions, infix, map, true, apply, eval

[re: imp]

Carl showed how to replace imp:
>     if (a = 3) or not (b = 4) then...
>               ^^^^^^^^-imp is logical IMPlication (not obvious here)

There is a more direct way, though with it you always have to evaluate
both sides of the expression (even with the unreleased short-circuiting
release of Euphoria):

    if (a = 3) <= (b = 4) then ...

    -- truth table:
    -- 1 <= 1   = 1
    -- 1 <= 0   = 0
    -- 0 <= 1   = 1
    -- 0 <= 0   = 1

Note the reversal of the arrow -- in math, implication is =>.


[re: discussions]

Irv commented:
> On the other hand, we got some good discussion going.
> So maybe it's better sometimes not to test things very
> carefully :)

Somehow I agree with this statement smile

None of the things in this mails are tested very carefully. smile


[re: infix]

Carl suggested a function infix declaration:
> so that infix functions (i.e. 3 + 4 rather than +(3,4)) are possible.
>
> Anyway, here's some provisional syntax:
>
> function infix is_the_same_as(object left, object right)
>     return compare({a}, {b})=0
> end function

Since an infix should always be a function, I am more inclined to do:

infix is_the_same_as(object left, object right)
    return not compare(left, right) -- definitely not {a} and {b}
end infix

Of course, routine_id() should still allow infix functions to be called
'normally'.

An alternative to this introduction of new keyword 'infix', is to allow
*all* two-argument functions (and one-argument ones) to be called as
operators. They are declared as functions, but both:

    is_the_same_as(a, b)
and
    a is_the_same_as b

are possible. All two-argument functions, when used as operators, should
have equal precedence. All one-argument functions, when used as operators,
should also have equal precedence. In line with Euphoria's current way of
evaluating expressions,

The operator precedence is thus amended as follows:
    calls with ()                       (function, type)
    unaries                             (-, +, not)
  * unary functions used as operators
    multiplicative arithmetic           (*, /)
    additive arithmetic                 (+, -)
    concatenation                       (&)
    comparison                          (<, >, <=, >=, =, !=)
  * binary functions used as operators
    logical binaries                    (and, or)               short-c.
    formation                           ({, , , })

Of course, other places are possible, and it is even also possible to
assign non-consecutive integers to the operators and let you designate
your own level of precedence in the function declaration, somehow.

Then it would be possible to do, e.g.

function succ(object x)
    return x + 1
end function

integer a
a = succ succ 8;
printf(1, "%d\n", {a}) -- 10

While the absence of () for one-argument functions are purely cosmetic in
most cases, the absence of () for two-argument functions -- which occurs
when they are called in the form of "a func b" instead of "func(a, b)" --
improves readability greatly in most cases -- if used right, that is.

Then all you have to do to have a "mod" operator is:

function mod(object a, object b)
    return remainder(a, b) -- maybe an "alias" would be nice??
end function

Even without it, you can already say

c = a remainder b
d = a power b
-- etc.


[map]

If comparison operators, used on a sequence, return a single boolean value
instead of a sequence of its results, Ralf will complain as follows:
> 3) It is in contrast with everything else we do in Euphoria:
>
>     {1,2,3} + 1 = *a sequence*
>
> 5) In my opinion 'sequence' is not a datatype, it is a container. A sequence
> itself is never a value, it are a number of values (atoms) that are
> structured together.

I agree with #5 but not with #3. If one wants such a sequence like {1,2,3}
+ 1, it would actually be cleaner (and probably less buggy, too)  if he
explicitly requests it. Therefore, I would want a built-in map function,
which works roughly as follows:

    -- x is a function that takes in one object
    function map(function x, sequence y) -- can't declare 'function'
        for i = 1 to length(y) do
            y[i] = x(y[i])
        end for
        return y
    end function

With it, we can say map(not, x) (supposing not were a function, not a
built-in).

We can extend this to a multiargument map:

    -- x is a function that takes in as many objects as there are
    -- elements in y -- this function stops as soon as one list-of-
    -- arguments has been used up.
    function map(function x, sequence_of_sequences y)
        sequence z
        z = {}
        while not find({}, y) do
            z = append(z, x(y[1][1], y[2][1], y[3][1], ...)) -- ???
            for i = 1 to length(y) do
                y[i] = y[i][2..length(y[i])]
            end for
        end while
        return z
    end function

With it, we can say map(not, {x}) to achieve the above, but also map(+,
{{1, 2, 3}, {6, 5, 4}}) to calculate {1, 2, 3} + {6, 5, 4}.

It would be even better if map converts atom elements in y to an infinite
sequence (actually, of the length of the shortest sequence in y)
whose all elements are the atom itself. Thus, map(+, {{1, 2, 3}, 1})
works. If all elements are atoms, convert any one of them to a length-1
sequence before doing the other conversions (i.e. take it as 1-element
sequence).

The benefits of this would be:
- improved readability (you know you are mapping a function to all the
  elements),
- you can use this to map your own functions as well,
- the internal implementation of built-in operators can be simplified,
- etc.

If you want recursion, you can implement + as e.g.

    function +(object a, object b)
        if atom(a) and atom(b) then
            return [+ A B] -- how-ever this is implemented internally
        end if
        return map(+, {a, b}) -- indirect recursion!
    end function


[re: true]

Ralf suggested:
> 6) You could make this one function to help fix your problems, while
> backwards this is not possible.
>
>     function true (object x)
>         if sequence (x) then
>             for index = 1 to length (x) do
>                 if not true (x) then
>                     return 0
>                 end if
>             end for
>         else
>             return x
>         end if
>     end function
>
>     if true ("Euphoria" = "Euphoria") then
>         -- Easy enough ?
>     end if

This would fail as soon as you execute true("Euphoria" = "Eu 2.0"), since
the = operator will already issue an error because "Euphoria" and "Eu 2.0"
have different lengths.


[apply]

I wrote, in the above:
>             z = append(z, x(y[1][1], y[2][1], y[3][1], ...)) -- ???

Wouldn't it be easier if we have an apply function:

    function apply(function func, sequence args)
        return func(args[1], args[2], ..., args[length(args)])
    end function

For example,
    x = apply(sprintf, {1, "%s\n", {"Hello!"}})
and
    x = sprintf(1, "%s\n", {"Hello!"})

would be the same. The difference is that you can actually build the list
of arguments yourself before you apply it to a function.


[eval]

Yet, a trickier approach is to be able to evaluate an Euphoria expression
embedded in a string in the current context (e.g. if it modifies a
variable, the variable remains modified; if it defines a function, the
function remains defined) and have a value returned. It can have some
statements, and at the end of it should be an expression. This expression
is returned.

eval should also prevent error messages, perhaps by setting a global
variable or something like that instead of crashing.

Examples:

eval("printf(1, \"%s\\n\", {\"Hello!\"}) 3 + 4") would do the printf and
return 7.

eval("x = 1/0 9") would not modify x, it will return an undefined value
(not 9), and it will set a global variable to state the division by zero
error.

puts(1, eval("integer x x = 8 \"abc \"))
printf(1, "%d\n", x)
will print: abc 8

With eval, we don't really need apply:
    x = apply(sprintf, {1, "%s\n", {"Hello!"}})
is equivalent to
    x = eval("sprintf(1, \"%s\\n\", {\"Hello!\"})")


Comments?

new topic     » topic index » view message » categorize

2. Re: imp, discussions, infix, map, true, apply, eval

> Comments?

1) I never thought someone would out-length me postwise :)

2) map()? Have you been studying Haskell?
   [Haskell is God awful functional language. It's unnecessarily
    over-recursive. Better than Prolog though <g> ]

3) I personally prefer "function infix name()...end function". It's
   more readable (IMHO) and easier to code ;)

4) From another post: Someone mentioned using <= for implication. I don't
   really like this as it implies (no pun intended) _reverse_ implication
   (which incidentally, I accidentally coded in my earlier post. It should
   have read "not a or b" rather than "a or not b". Oops.)

Carl

--
Carl R White -- Final Year Computer Science at the University of Bradford
E-mail...: cyrek- at -bigfoot.com -- Remove the hyphens before mailing. Ta :)
URL......: http://www.bigfoot.com/~cyrek/
Ykk rnyllaqur rgiokc cea nyemdok ymc giququezka caysgr -- B.Q.Vgesa

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu