How can I avoid passing variables through multiple functions? - user-interface

While doing GUI programming (in Perl), I often have the case where I have a main package/function x that calls a package/function y, which in turn calls package/function z. But, when I have a variable in x (e.g. a reference to a widget) that I need to access in z, I have to then pass it through y because I don't want to use globals.
Is there a better way to do this? As my program gets bigger, I seem to have more and more variables being passed through packages/functions just so that I can access them in sub packages/functions.

You seem to think this is a bug. It's a feature! It means that if you come back to the program in months or years, you know how and where your data is being used.
Keep in mind that it is not in general empty information to pass a variable a through y to get to z. The reason is that y might instead generate its own version of a; from looking at x or z alone you wouldn't be able to tell with global variables. If you pass it through y, at least you know that y starts out with something generated by x.
Keep in mind that you also might find that you need to refactor your code:
x produces a
x calls y with a
y produces b
y calls z with a and b
could be changed to
x produces a
x calls y
y produces and returns b
x calls z with a and b
in some cases.

Related

Continuous functions in Isabelle

I want to define a continuous function on an interval of the real line -- [a,b), [a,b], (a,b), or (a,b] (where a < b and either could possibly be infinite) -- in Isabelle, or state that a function is continuous on such an interval.
I believe what I want is continuous_on s f because
"continuous_on s f ⟷ (∀x∈s. (f ⤏ f x) (at x within s))"
(which I got from here:https://isabelle.in.tum.de/library/HOL/HOL/Topological_Spaces.html#Topological_Spaces.topological_space_class.at_within|const)
So I think "s" should be an interval but I'm not sure how best to represent that.
So I would like to know how I could set "s" to any of the types of set intervals I list above. Thank you!
The answer to your question
In every ordered type you can write {a..b} for the closed interval from a to b. For the open/half-open variants there are {a<..b}, {a..<b}, {a<..<b}, {a..}, {..b}, {a<..}, and {..<b}.
These are defined in HOL.Set_Interval and there internal names are things like lessThan, atLeastAtMost, etc.
So in your case, you can simply write something like continuous_on {a..b} f.
It takes some time to understand how to do arguments about limits, continuity, etc. in a theorem prover efficiently. Don't be afraid to ask, either here or on the Zulip. You can of course always do things the hard way (with e.g. ε–δ reasoning) but once you become more proficient in using the library a lot of things become much easier. Which brings me to:
Addendum: Filters
Note however that to really reason about continuity in Isabelle in an idiomatic way you will have to understand filters, which are (among other things) a way to talk about ‘neighbourhoods of points’. There is the definition continuous which takes a function at a filter and can be used to say that a function is continuous at a given point with some conditions.
For instance, there are filters
nhds x, which describes the neighbourhoods of x (i.e. everything that is sufficiently close to x)
at x within A, which describes the pointed neighbourhood of x intersected with A – i.e. you approach x without every reaching it and while staying fully inside the set A
at x, which is simply at x within UNIV, i.e. the pointed neighbourhood of x without further restricitions
at_left x and at_right x for e.g. the real numbers, which are defined as at x within {..<x} and at x within {x<..}, i.e. the left and right neighbourhoods of x
Then you can write things like continuous (at x) F or continuous (at_right x) F. If I recall correctly, continuous_on A f is equivalent to ∀x∈A. continuous (at x within A) f.
Filters are also useful for many other related things, like limits, open/closed sets, uniform continuity, and derivatives.
This paper explains how filters are used in the Isabelle analysis library. It also has a short section about continuity.

Which is better in OCaml pattern matching, `when` or `if-then-else`?

Let's say we have a type called d:
type d = D of int * int
And we want to do some pattern matching over it, is it better to do it this way:
let dcmp = function
| D (x, y) when x > y -> 1
| D (x, y) when x < y -> -1
| _ -> 0
or
let dcmp = function
| D (x, y) ->
if x > y then 1 else if x < y then -1 else 0
Just in general is better to match patterns with many "when" cases or to match one pattern and the put an "if-then-else" in it?
And where can I get more information about such matters, like good practices in OCaml and syntactic sugars and such?
Both approaches have their cons and pros so they should be used accordingly to the context.
The when clause is easier to understand than if because it has only one branch, so you can digest a branch in a time. It comes with the price that when we analyze a clause in order to understand its path condition we have to analyze all branches before it (and negate them), e.g., compare your variant with the following definition, which is equivalent,
let dcmp = function
| D (x, y) when x > y -> 1
| D (x, y) when x = y -> 0
| _ -> -1
Of course, the same is true for if/then/else construct it is just harder to accidentally rearrange branches (e.g., during refactoring) in the if/then/else expression and completely change the logic of the expression.
In addition, the when guards may prevent the compiler from performing decision tree optimizations1 and confuse2 the refutation mechanism.
Given this, the only advantage to using when instead of if in this particular example is that when syntax looks more appealing as it perfectly lined up and it is easier for the human brain to find where are the conditions and their corresponding values, i.e., it looks more like a truth-table. However, if we will write
let dcmp (D (x,y)) =
if x = y then 0 else
if x > y then 1 else -1
we can achieve the same level of readability.
To summarize, it is better to use when when it is impossible or nearly impossible to express the same code with if/then/else. To improve readability it is better to factor your logic into helper functions with readable names. For example, with dcmp the best solution is to use neither if or when, e.g.,
let dcmp (D (x,y)) = compare x y
1)In this particular case the compiler will generate the same code for when and if/then/else. But in more general cases, guards may prevent the matching compiler from generating the efficient code, especially when branches are disjoint. In our case, the compiler just noticed that we're repeating the same branch and coalesced them into a single branch and turned it back into the if/then/else expression, e.g., here is the cmm output of the function with the when guards,
(if (> x y) 3 (if (< x y) -1 1))
which is exactly the same code as generated by the if/then/else version of the dcmp function.
2) Not to the state where it will not notice a missing branch, of course, but to the state where it will report missing branches less precisely or will ask you to add unnecessary branches.
Quoting the OCaml Towards Clarity and Grace style guide:
Code is more often read than written - make the life of the reader easy
and
Less code is better, cryptic code is worse
The first makes me think that the version with multiple when clauses is the better choice, as it makes it easy to predict or evaluate the result when reading the code depending on condition. The second goes further, against the if-then-else because, even if shorter, is cryptic when looking from afar.
Also, in the section Functions, we find out that "Pattern matching is the preferred way to define functions"
From a Haskell functional programmer's point of view.

Math inside predicate header

Is there a way to make this work?
add(X, X + 1)
input: add(1, Y).
expected output: Y = 2.
output: Y = 1+1.
Or is it only possible by doing this?
add(X, Y):- Y is X+1.
Historically, there have been many attempts to provide this functionality. Let me give as early examples CLP(ℜ) (about 1986) or more recently Prolog IV. However, sooner or later, one realizes that a programmer needs a finer control about the kind of unification that is employed. Take as example a program that wants to differentiate a formula. In that situation an interpreted functor would not be of any use. For this reason most constraints ship today as some added predicates leaving functors otherwise uninterpreted. In this manner they also fit into ISO-Prolog which permits constraints as extensions.
From a programmer's viewpoint, an extension as yours would reduce the number of auxiliary variables needed, however, it also would require to interpret all terms to this end which produces a lot of extra overhead.

Why does Go slice `append()` not take a reference?

Go Lang's slice append() might allocate a new backing array to make room for the new item. Thus, after a call z = append(x,y), if z's front most elements are modified, x is essentially unspecified -- it might or might not have the same backing array as z, and z could mutate its backing array with z[0] = foo, which thus might or might not modify x's backing array.
So, why let this ugliness surface? Instead making it a program bug to assign the result of append to anything but its first argument, why not have append take a *[]T instead, so no reassignment is needed and no undefined variable is left dangling.
This wouldn't solve every case, because a = x; append(&x,y) would still make a undefined, but a partial improvement seems better than none.
It's not quite true that in your first example (z = append(x, y)), x is undefined. Instead, x still points to the original contents of x, while z points to those contents and then some. As you mention, there are two possibilities:
cap(x) > len(x), in which case append simply returns x[:len(x)+1] (ie, extends the length of the returned slice to contain one extra element)
cap(x) == len(x), in which case append creates another array by copying over the contents of x and then appends y as the len(x)-th element.
In either of these cases, x is left largely unchanged in the sense that all of the elements of x are still there. You obviously have to be careful now that you potentially have two references to the same underlying data, but the point stands that keeping x around can be useful.
That said, I agree that maybe having append take a pointer might be simpler, and maybe this possible use case that I've just described isn't common enough to warrant the potentially confusing, mildly more verbose semantics.

OCaml: order of input two values

In functional language order of evaluation function arguments should have no sense.
However, even simplest programs could be not quite-functional. Here the code reads two integers and raises one into the power of other:
let pwr x y =
let rec pwrx = function 0 -> 1 | y -> x * pwrx (y - 1)
in pwrx y;;
print_int (pwr (read_int ()) (read_int ()));;
The code, obviously, reads the second argument first: if 5 and 4 are entered, result is 1024.
I suppose problem is in mishandling the language and lack of understanding its ideology. How should I wrote such things properly? Should I read two values in separate lines before calling function?
let x = read_int();;
let y = read_int();;
print_int (pwr x y);;
It works but looks like bit overhead - isn't it?
The problem is not the lack of functional aspect of the language, but the fact that a feature like read_line is not functional per se since it relies on an external input from stdin.
You should use local declarations like you did (and it's even pointed out here on official documentation). There's no real overhead since they're just declarations.
If you want this to be part of a single function and use purely local variables the code would be:
let x = read_int() in
let y = read_int() in
print_int (pwr x y)
Generally, speaking, if you want to enforce a particular order, you should use let statements to do it. It's slightly less pretty looking, but not everything can look elegant all the time, especially input and output in functional programming.

Resources