Asked  7 Months ago    Answers:  5   Viewed   69 times

What is the difference between the dot (.) and the dollar sign ($)?

As I understand it, they are both syntactic sugar for not needing to use parentheses.



The $ operator is for avoiding parentheses. Anything appearing after it will take precedence over anything that comes before.

For example, let's say you've got a line that reads:

putStrLn (show (1 + 1))

If you want to get rid of those parentheses, any of the following lines would also do the same thing:

putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1

The primary purpose of the . operator is not to avoid parentheses, but to chain functions. It lets you tie the output of whatever appears on the right to the input of whatever appears on the left. This usually also results in fewer parentheses, but works differently.

Going back to the same example:

putStrLn (show (1 + 1))
  1. (1 + 1) doesn't have an input, and therefore cannot be used with the . operator.
  2. show can take an Int and return a String.
  3. putStrLn can take a String and return an IO ().

You can chain show to putStrLn like this:

(putStrLn . show) (1 + 1)

If that's too many parentheses for your liking, get rid of them with the $ operator:

putStrLn . show $ 1 + 1
Tuesday, June 1, 2021
answered 7 Months ago

Use sigaction() unless you've got very compelling reasons not to do so.

The signal() interface has antiquity (and hence availability) in its favour, and it is defined in the C standard. Nevertheless, it has a number of undesirable characteristics that sigaction() avoids - unless you use the flags explicitly added to sigaction() to allow it to faithfully simulate the old signal() behaviour.

  1. The signal() function does not (necessarily) block other signals from arriving while the current handler is executing; sigaction() can block other signals until the current handler returns.
  2. The signal() function (usually) resets the signal action back to SIG_DFL (default) for almost all signals. This means that the signal() handler must reinstall itself as its first action. It also opens up a window of vulnerability between the time when the signal is detected and the handler is reinstalled during which if a second instance of the signal arrives, the default behaviour (usually terminate, sometimes with prejudice - aka core dump) occurs.
  3. The exact behaviour of signal() varies between systems — and the standards permit those variations.

These are generally good reasons for using sigaction() instead of signal(). However, the interface of sigaction() is undeniably more fiddly.

Whichever of the two you use, do not be tempted by the alternative signal interfaces such as sighold(), sigignore(), sigpause() and sigrelse(). They are nominally alternatives to sigaction(), but they are only barely standardized and are present in POSIX for backwards compatibility rather than for serious use. Note that the POSIX standard says their behaviour in multi-threaded programs is undefined.

Multi-threaded programs and signals is a whole other complicated story. AFAIK, both signal() and sigaction() are OK in multi-threaded applications.

Cornstalks observes:

The Linux man page for signal() says:

  The effects of signal() in a multi-threaded process are unspecified.

Thus, I think sigaction() is the only that can be used safely in a multi-threaded process.

That's interesting. The Linux manual page is more restrictive than POSIX in this case. POSIX specifies for signal():

If the process is multi-threaded, or if the process is single-threaded and a signal handler is executed other than as the result of:

  • The process calling abort(), raise(), kill(), pthread_kill(), or sigqueue() to generate a signal that is not blocked
  • A pending signal being unblocked and being delivered before the call that unblocked it returns

the behavior is undefined if the signal handler refers to any object other than errno with static storage duration other than by assigning a value to an object declared as volatile sig_atomic_t, or if the signal handler calls any function defined in this standard other than one of the functions listed in Signal Concepts.

So POSIX clearly specifies the behaviour of signal() in a multi-threaded application.

Nevertheless, sigaction() is to be preferred in essentially all circumstances — and portable multi-threaded code should use sigaction() unless there's an overwhelming reason why it can't (such as "only use functions defined by Standard C" — and yes, C11 code can be multi-threaded). Which is basically what the opening paragraph of this answer also says.

Tuesday, June 1, 2021
answered 7 Months ago

Put simply, . is function composition, just like in math:

f (g x) = (f . g) x

In your case, you are creating a new function, sumEuler that could also be defined like this:

sumEuler x = sum (map euler (mkList x))

The style in your example is called "point-free" style -- the arguments to the function are omitted. This makes for clearer code in many cases. (It can be hard to grok the first time you see it, but you will get used to it after a while. It is a common Haskell idiom.)

If you are still confused, it may help to relate . to something like a UNIX pipe. If f's output becomes g's input, whose output becomes h's input, you'd write that on the command-line like f < x | g | h. In Haskell, . works like the UNIX |, but "backwards" -- h . g . f $ x. I find this notation to be quite helpful when, say, processing a list. Instead of some unwieldy construction like map (x -> x * 2 + 10) [1..10], you could just write (+10) . (*2) <$> [1..10]. (And, if you want to only apply that function to a single value; it's (+10) . (*2) $ 10. Consistent!)

The Haskell wiki has a good article with some more detail:

Tuesday, June 22, 2021
answered 6 Months ago

There are two key differences:

First, attributes assigned to a view via style will apply only to that view, while attributes assigned to it via android:theme will apply to that view as well as all of its children. For example, consider this style resource:

<style name="my_background">
    <item name="android:background">@drawable/gradient</item>

If we apply it to a LinearLayout with three child TextViews by using style="@style/my_background", then the linearlayout will draw with a gradient background, but the backgrounds of the textviews will be unchanged.

If instead we apply it to the LinearLayout using android:theme="@style/my_background" then the linearlayout and each of the three textviews will all use the gradient for their background.

The second key difference is that some attributes only affect views if they are defined in that view's theme. For example, consider this style resource:

<style name="checkboxes">
    <item name="colorAccent">#caf</item>
    <item name="colorControlNormal">#caf</item>

If I apply this to a CheckBox using style="@style/checkboxes", nothing will happen. If instead I apply it using android:theme="@style/checkboxes", the color of the checkbox will change.

Just like the first rule said, styles containing theme attributes will apply to all children of the view with the android:theme attribute. So I can change the color of all checkboxes in a linearlayout by applying android:theme="@style/checkboxes" to my linearlayout.

Sunday, August 22, 2021
answered 4 Months ago

You're getting tripped up by haskell's precedence rules for operators, which are confusing.

When you write

x = fromIntegral.sum lst

Haskell sees that as the same as:

x = fromIntegral.(sum lst)

What you meant to write was:

x = (fromIntegral.sum) lst
Friday, October 29, 2021
Gordon Linoff
answered 1 Month ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :