问:
How does Haskell pick a type for an ambiguous expression
If an expression can be typed in several ways, how does Haskell pick which one to use?

Motivating example

Take this example:

```<code>$ ghci
GHCi, version 8.8.4: https://www.haskell.org/ghc/  :? for help
Prelude> import Data.Ratio (Ratio)
Prelude Data.Ratio> f z s = show $ truncate $ z + (read s)
Prelude Data.Ratio> :type f
f :: (RealFrac a, Read a) => a -> String -> String
Prelude Data.Ratio> s = take 30 (cycle "12345")
Prelude Data.Ratio> s
"123451234512345123451234512345"
Prelude Data.Ratio> f 0 s
"123451234512345121227855101952"
Prelude Data.Ratio> f (0::Double) s
"123451234512345121227855101952"
Prelude Data.Ratio> f (0::Float) s
"123451235679745417161721511936"
Prelude Data.Ratio> f (0::Ratio Integer) (s ++ "%1")
"123451234512345123451234512345"
Prelude Data.Ratio> show $ truncate $ read s
"123451234512345121227855101952"
</code>```

When I used 0 without any type, I got the same result as for (0::Double). So it seems to me that when I just invoke f 0 s, it uses a version of read that produces a Double, and a version of truncate that turns that Double into some integral type. I introduces the variable z so I could have some easy control over the type here. With that I could show that other interpretations are possible, e.g. using Float or exact ratios. So why Double? The last line, which omits the addition, shows that the behavior is independent of that zero constant.

I guess something tells Haskell that Double is a more canonical type than others, either in general or when used as a RealFrac, so if it can interpret an expression using Double as an intermediate result, but also some other types, then it will prefer the Double interpretation.

Core questions

Is my interpretation observed behavior correct, and there is an implicit type default here?

What is the name for this kind of preference?

Is there a way to disable such a choice of canonical type and enforce explicit type specifications for things that can be interpreted in multiple ways?

Own research

I've read that https://en.wikibooks.org/wiki/Haskell/Type_basics_II#Polymorphic_guesswork writes

With no other restrictions, 5.12 will assume the default Fractional type of Double, so (-7) will become a Double as well.

That appears to confirm my assumption that Double is somehow blessed as the default type for some parent category of RealFrac. It still doesn't offer a name for that concept, nor a complete list of the rules around that.

Background

The situation I actually want to handle is more like this:

```<code>f :: Integer -> String -> Integer
f scale str = truncate $ (fromInteger scale) * (read str)
</code>```

So I want a function that takes a string, reads it as a decimal fraction, multiplies it with a given number, then truncates the result back to an integer. I was very surprised to find that this compiles without me specifying the intermediate fractional type anywhere.

答:
If there is an ambiguous type variable v with a Num v constraint, it gets defaulted to Integer or Double, tried in that order, whichever satisfies all other constraints on v.

Those defaulting rules are explained in the Haskell Report: https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-620004

The GHC manual also explains additional defaulting rules in GHCi (this means trying things in GHCi will not give you an accurate picture of what is going on when you compile a program): https://downloads.haskell.org/ghc/latest/docs/html/users_guide/ghci.html#type-defaulting-in-ghci

Body:
If an expression can be typed in several ways, how does Haskell pick which one to use?

Motivating example

Take this example:

$ ghci
GHCi, version 8.8.4: https://www.haskell.org/ghc/  :? for help
Prelude> import Data.Ratio (Ratio)
Prelude Data.Ratio> f z s = show $ truncate $ z + (read s)
Prelude Data.Ratio> :type f
f :: (RealFrac a, Read a) => a -> String -> String
Prelude Data.Ratio> s = take 30 (cycle "12345")
Prelude Data.Ratio> s
"123451234512345123451234512345"
Prelude Data.Ratio> f 0 s
"123451234512345121227855101952"
Prelude Data.Ratio> f (0::Double) s
"123451234512345121227855101952"
Prelude Data.Ratio> f (0::Float) s
"123451235679745417161721511936"
Prelude Data.Ratio> f (0::Ratio Integer) (s ++ "%1")
"123451234512345123451234512345"
Prelude Data.Ratio> show $ truncate $ read s
"123451234512345121227855101952"

When I used 0 without any type, I got the same result as for (0::Double). So it seems to me that when I just invoke f 0 s, it uses a version of read that produces a Double, and a version of truncate that turns that Double into some integral type. I introduces the variable z so I could have some easy control over the type here. With that I could show that other interpretations are possible, e.g. using Float or exact ratios. So why Double? The last line, which omits the addition, shows that the behavior is independent of that zero constant.

I guess something tells Haskell that Double is a more canonical type than others, either in general or when used as a RealFrac, so if it can interpret an expression using Double as an intermediate result, but also some other types, then it will prefer the Double interpretation.

Core questions

Is my interpretation observed behavior correct, and there is an implicit type default here?

What is the name for this kind of preference?

Is there a way to disable such a choice of canonical type and enforce explicit type specifications for things that can be interpreted in multiple ways?

Own research

I've read that https://en.wikibooks.org/wiki/Haskell/Type_basics_II#Polymorphic_guesswork writes

With no other restrictions, 5.12 will assume the default Fractional type of Double, so (-7) will become a Double as well.

That appears to confirm my assumption that Double is somehow blessed as the default type for some parent category of RealFrac. It still doesn't offer a name for that concept, nor a complete list of the rules around that.

Background

The situation I actually want to handle is more like this:

f :: Integer -> String -> Integer
f scale str = truncate $ (fromInteger scale) * (read str)

So I want a function that takes a string, reads it as a decimal fraction, multiplies it with a given number, then truncates the result back to an integer. I was very surprised to find that this compiles without me specifying the intermediate fractional type anywhere.


来源: stackexchange

问:
What is the logic behind this example?

def myfunc(n):
  return lambda a : a * n

mytripler = myfunc(3)

print(mytripler(11))
```

I am trying to learn about the lambda function in python. I understand the other examples given inside w3schools about the Lambda function. This example, however, I could not wrap my head around. How is it that mytripler(11) multiplies 3 by 11?

答:
Let's take a step back: What is a function?

One definition could be that's a construct where you give it arguments, it does something and it returns a value (Let's ignore for now the cases where you don't give any arguments or where you don't receive any return value)

In Python, since everything is an object, this kind of construct is a value that can be assigned a name. For example:

>>> def example_function(argument):
...     result = argument * 42
...     return result
...
>>> other_name_for_example_function = example_function
>>> example_function(3)
126
>>> other_name_for_example_function(3)
126
>>> example_function == other_name_for_example_function
True
>>> example_function is other_name_for_example_function
True
```
<p>Note that in the comparison made at the end, I do not call these functions, I just compare the value of <code>example_function</code> and <code>other_name_for_example_function</code> which in this case is the same "function mechanism".</p>
<p>Now, lambdas are another way to define a function but it's more restricted and the function isn't assigned a name automatically. Let's take the same example but with lambdas:</p>
<pre class="lang-py prettyprint-override"><code>>>> example_lambda = lambda argument: argument * 42
>>> other_name_for_example_lambda = example_lambda
>>> example_lambda(3)
126
>>> other_name_for_example_lambda(3)
126
>>> example_lambda == other_name_for_example_lambda
True
>>> example_lambda is other_name_for_example_lambda
True
</code>```

Now if we replace the function call of your example with its content, it would look like this:

>>> n = 3   # just you see where that value will be used
>>> mytripler = lambda a: a * n
>>> a = 11  # also to see where that value will be used
>>> mytripler(a)
33
```

So, in your example,

myfunc() provide a "function mechanism" as a return value. In the definition of that "function mechanism", you have inserted the value 3 which is an argument of myfunc()

You assign the name mytripler to that function returned

You call it like you would with any function

Does that help you understand?

ContentLicense: CC BY-SA 4.0

Title: What is the logic behind this example?

Body:
def myfunc(n):
  return lambda a : a * n

mytripler = myfunc(3)

print(mytripler(11))

I am trying to learn about the lambda function in python. I understand the other examples given inside w3schools about the Lambda function. This example, however, I could not wrap my head around. How is it that mytripler(11) multiplies 3 by 11?

Body:
Let's take a step back: What is a function?

One definition could be that's a construct where you give it arguments, it does something and it returns a value (Let's ignore for now the cases where you don't give any arguments or where you don't receive any return value)

In Python, since everything is an object, this kind of construct is a value that can be assigned a name. For example:

>>> def example_function(argument):
...     result = argument * 42
...     return result
...
>>> other_name_for_example_function = example_function
>>> example_function(3)
126
>>> other_name_for_example_function(3)
126
>>> example_function == other_name_for_example_function
True
>>> example_function is other_name_for_example_function
True

Note that in the comparison made at the end, I do not call these functions, I just compare the value of example_function and other_name_for_example_function which in this case is the same "function mechanism".

Now, lambdas are another way to define a function but it's more restricted and the function isn't assigned a name automatically. Let's take the same example but with lambdas:

>>> example_lambda = lambda argument: argument * 42
>>> other_name_for_example_lambda = example_lambda
>>> example_lambda(3)
126
>>> other_name_for_example_lambda(3)
126
>>> example_lambda == other_name_for_example_lambda
True
>>> example_lambda is other_name_for_example_lambda
True

Now if we replace the function call of your example with its content, it would look like this:

>>> n = 3   # just you see where that value will be used
>>> mytripler = lambda a: a * n
>>> a = 11  # also to see where that value will be used
>>> mytripler(a)
33

So, in your example,

myfunc() provide a "function mechanism" as a return value. In the definition of that "function mechanism", you have inserted the value 3 which is an argument of myfunc()

You assign the name mytripler to that function returned

You call it like you would with any function

Does that help you understand?


问:
How to avoid overlapping of random numbers?
On Clicking button Click Me! How to avoid overlapping of random numbers?
It will generate random numbers but there are some numbers which are overlapping how to avoid this...  , Here I am not talking about duplicacy of random numbers , I want  to avoid overlapping of random numbers....

const circle = document.querySelector(".circle");
const addNumBtn = document.querySelector('#addNumBtn')

function randomValue() {
  let random = Math.floor(Math.random() * 50) + 1;
  return random;
}
function randomColor(){
  let r = Math.floor(Math.random() * 255) + 1;
  let g = Math.floor(Math.random() * 255) + 1;
  let b = Math.floor(Math.random() * 255) + 1;
  return `rgba(${r},${g},${b})`
}
function randomSize(){
  let size = Math.floor(Math.random() * 30) + 8;
  return `${size}px`
}
function randNum() {
  let randnum = document.createElement("p");
  randnum.classList.add('numStyle')
  randnum.style.color=randomColor();
  randnum.style.fontSize=randomSize();
  randnum.textContent = randomValue();
  randnum.style.position = 'absolute'
  randnum.style.top = `${randomValue()}px`
  randnum.style.left = `${randomValue()}px`
  randnum.style.bottom = `${randomValue()}px`
  randnum.style.right = `${randomValue()}px`
  circle.append(randnum);
}

addNumBtn.addEventListener('click',randNum)```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.circle {
  aspect-ratio: 1;
  width: 300px;
  background-color: black;
  border-radius: 50%;
  position: relative;
  overflow:hidden;
}

#addNumBtn{
  position:absolute;
  top:0;
  left:0;
}

.numStyle{
  font-family:"roboto",sans-serif;
}</code>```

//On Clicking button Click Me! I want to place all the random numbers inside the circle
//together not one by one, at a time all numbers should be placed inside the circle by
//clicking
the button Click Me!

    <button id="addNumBtn">Click Me!</button>```

答:
You need to loop over the random number generator for the amount of times you wish to display the created number element in the circle. You can create and return an array of values in randomValue() function, then loop over that array in randNum() function.

Also, I assume you want the output of the appended element to spread out over the entirety of the circle element yes? If so, you need to randomize the position of the element relative to the size of the circle, not the randomValue functions returned value.

EDIT:

OP asked after posting answer: There are some numbers at circles border side which are not properly visible how to solve that?

Because of the box model of elements, the border of the circle element is square, not round though the viewable content of the circle element is round due to its border-radius css.

You can use a helper function that will determine if the randomly generated numbers for x and y, or left and top, are within the border-radius of the circle element using the size of the radius and the center point of the x and y coords of the circle.

Credit for helper function: Simon Sarris:

```<code>function pointInCircle(x, y, cx, cy, rad) {
  const distancesquared = (x - cx) * (x - cx) + (y - cy) * (y - cy);
  return distancesquared <= rad * rad;
}
</code>```

We wrap everything inside a while loop that checks if a counter has reached 50. Inside the loop we run the function that creates the randomly generated positions -> randomPos(). Then we run a conditional that will check to see if the randomly generated points are within the circle using the function pointInCircle(x, y, cx, cy, rad). If this conditional returns true we create the number elements, style and append the number elements to the circle and iterate our counter value by one.

const circle = document.querySelector(".circle");
const addNumBtn = document.querySelector('#addNumBtn');
// we set the width of the circle element in JS and pass
// it to CSS using a css variable and the root element
const circleWidth = 350;
document.documentElement.style.setProperty('--circleWidth', `${circleWidth}px`);

// NOTE: '~~' -> is quicker form of writing Math.floor()
// runs faster on most browsers.

function randomPos(min, max) {
  return ~~(Math.random() * (max - min + 1) + min)
}

// return a random value between 1 and 50
function randomValue(){
  return ~~(Math.random() * 50) + 1;
}

function randomColor() {
  let r = ~~(Math.random() * 255) + 1;
  let g = ~~(Math.random() * 255) + 1;
  let b = ~~(Math.random() * 255) + 1;
  return `rgba(${r},${g},${b})`
}

function randomSize() {
  let size = ~~(Math.random() * 30) + 8;
  return `${size}px`
}

// add a helper function to find the center of the
// circle and calculate distance to the edge of circle
// x and y are the randomly generated points
// cx, cy are center of circle x and y repsectively
// rad is circle radius
function pointInCircle(x, y, cx, cy, rad) {
  const distancesquared = (x - cx) * (x - cx) + (y - cy) * (y - cy);
  return distancesquared <= rad * rad;
}

// you can remove valArray array if you do not want the 50 numbers to not be repeated
const valArray = [];

function randNum() {
  // add a counter
  let count = 1;
  // while loop to check if the counter has reached the target 50
  while (count <= 50) {
    // set the randomly generated val
    let val = randomValue();
    // random size = string with px added
    let randSize = randomSize();
    // random size = the exact number => typeof number
    let posSize = randSize.split('px')[0];
    // an array to hold our randomly positioned number values
    // uses helper function randonPos
    // pass in the 1 and the circle width minus the font size
    let ran = [randomPos(1, circleWidth - posSize), randomPos(1, circleWidth - posSize)];
    // conditional to check bounds of circle using helper function
    // we pass in the ran array, center points and radius
    // we add buffers to accommodate for the font size
    // you can remove !valArray.includes(val) if you do not want the 50 numbers to not be repeated
    if (pointInCircle(ran[0], ran[1], circleWidth/2-posSize, circleWidth/2-posSize, circleWidth / 2 - posSize) && !valArray.includes(val)) {
      // you can remove valArray.push(val); if you do not want the 50 numbers to not be repeated
      valArray.push(val);
      // if the conditional returns true,
      // create the element, style and append
      let randnum = document.createElement("p");
      randnum.classList.add('numStyle');
      randnum.style.color = randomColor();
      randnum.style.fontSize = randSize;
      randnum.textContent = val;
      randnum.style.position = 'absolute';
      randnum.style.top = `${ran[0]}px`;
      randnum.style.left = `${ran[1]}px`;
      circle.append(randnum);
      // iterate the counter
      count++;
    }
  }
}

addNumBtn.addEventListener('click', randNum)```
<pre class="snippet-code-css lang-css prettyprint-override"><code>html {
  --circle-width: 300px;
}

.circle {
  aspect-ratio: 1;
  width: var(--circleWidth);
  background-color: black;
  border-radius: 50%;
  position: relative;
  overflow: hidden;
  padding: .5rem;
}

#addNumBtn {
  position: absolute;
  top: 0;
  left: 0;
}

.numStyle {
  font-family: "roboto", sans-serif;
}</code>```

//On Clicking button Click Me! I want to place all the random numbers inside the circle //together not one by one, at a time all numbers should be placed inside the circle by //clicking the button Click Me!

<button id="addNumBtn">Click Me!</button>```

Body:
On Clicking button Click Me! How to avoid overlapping of random numbers?
It will generate random numbers but there are some numbers which are overlapping how to avoid this...  , Here I am not talking about duplicacy of random numbers , I want  to avoid overlapping of random numbers....

const circle = document.querySelector(".circle");
const addNumBtn = document.querySelector('#addNumBtn')

function randomValue() {
  let random = Math.floor(Math.random() * 50) + 1;
  return random;
}
function randomColor(){
  let r = Math.floor(Math.random() * 255) + 1;
  let g = Math.floor(Math.random() * 255) + 1;
  let b = Math.floor(Math.random() * 255) + 1;
  return `rgba(${r},${g},${b})`
}
function randomSize(){
  let size = Math.floor(Math.random() * 30) + 8;
  return `${size}px`
}
function randNum() {
  let randnum = document.createElement("p");
  randnum.classList.add('numStyle')
  randnum.style.color=randomColor();
  randnum.style.fontSize=randomSize();
  randnum.textContent = randomValue();
  randnum.style.position = 'absolute'
  randnum.style.top = `${randomValue()}px`
  randnum.style.left = `${randomValue()}px`
  randnum.style.bottom = `${randomValue()}px`
  randnum.style.right = `${randomValue()}px`
  circle.append(randnum);
}

addNumBtn.addEventListener('click',randNum)

.circle {
  aspect-ratio: 1;
  width: 300px;
  background-color: black;
  border-radius: 50%;
  position: relative;
  overflow:hidden;
}

#addNumBtn{
  position:absolute;
  top:0;
  left:0;
}

.numStyle{
  font-family:"roboto",sans-serif;
}

//On Clicking button Click Me! I want to place all the random numbers inside the circle
//together not one by one, at a time all numbers should be placed inside the circle by
//clicking
the button Click Me!

    <button id="addNumBtn">Click Me!</button>

Body:
You need to loop over the random number generator for the amount of times you wish to display the created number element in the circle. You can create and return an array of values in randomValue() function, then loop over that array in randNum() function.

Also, I assume you want the output of the appended element to spread out over the entirety of the circle element yes? If so, you need to randomize the position of the element relative to the size of the circle, not the randomValue functions returned value.

EDIT:

OP asked after posting answer: There are some numbers at circles border side which are not properly visible how to solve that?

Because of the box model of elements, the border of the circle element is square, not round though the viewable content of the circle element is round due to its border-radius css.

You can use a helper function that will determine if the randomly generated numbers for x and y, or left and top, are within the border-radius of the circle element using the size of the radius and the center point of the x and y coords of the circle.

Credit for helper function: Simon Sarris:

function pointInCircle(x, y, cx, cy, rad) {
  const distancesquared = (x - cx) * (x - cx) + (y - cy) * (y - cy);
  return distancesquared <= rad * rad;
}

We wrap everything inside a while loop that checks if a counter has reached 50. Inside the loop we run the function that creates the randomly generated positions -> randomPos(). Then we run a conditional that will check to see if the randomly generated points are within the circle using the function pointInCircle(x, y, cx, cy, rad). If this conditional returns true we create the number elements, style and append the number elements to the circle and iterate our counter value by one.

const circle = document.querySelector(".circle");
const addNumBtn = document.querySelector('#addNumBtn');
// we set the width of the circle element in JS and pass
// it to CSS using a css variable and the root element
const circleWidth = 350;
document.documentElement.style.setProperty('--circleWidth', `${circleWidth}px`);

// NOTE: '~~' -> is quicker form of writing Math.floor()
// runs faster on most browsers.

function randomPos(min, max) {
  return ~~(Math.random() * (max - min + 1) + min)
}

// return a random value between 1 and 50
function randomValue(){
  return ~~(Math.random() * 50) + 1;
}

function randomColor() {
  let r = ~~(Math.random() * 255) + 1;
  let g = ~~(Math.random() * 255) + 1;
  let b = ~~(Math.random() * 255) + 1;
  return `rgba(${r},${g},${b})`
}

function randomSize() {
  let size = ~~(Math.random() * 30) + 8;
  return `${size}px`
}

// add a helper function to find the center of the
// circle and calculate distance to the edge of circle
// x and y are the randomly generated points
// cx, cy are center of circle x and y repsectively
// rad is circle radius
function pointInCircle(x, y, cx, cy, rad) {
  const distancesquared = (x - cx) * (x - cx) + (y - cy) * (y - cy);
  return distancesquared <= rad * rad;
}

// you can remove valArray array if you do not want the 50 numbers to not be repeated
const valArray = [];

function randNum() {
  // add a counter
  let count = 1;
  // while loop to check if the counter has reached the target 50
  while (count <= 50) {
    // set the randomly generated val
    let val = randomValue();
    // random size = string with px added
    let randSize = randomSize();
    // random size = the exact number => typeof number
    let posSize = randSize.split('px')[0];
    // an array to hold our randomly positioned number values
    // uses helper function randonPos
    // pass in the 1 and the circle width minus the font size
    let ran = [randomPos(1, circleWidth - posSize), randomPos(1, circleWidth - posSize)];
    // conditional to check bounds of circle using helper function
    // we pass in the ran array, center points and radius
    // we add buffers to accommodate for the font size
    // you can remove !valArray.includes(val) if you do not want the 50 numbers to not be repeated
    if (pointInCircle(ran[0], ran[1], circleWidth/2-posSize, circleWidth/2-posSize, circleWidth / 2 - posSize) && !valArray.includes(val)) {
      // you can remove valArray.push(val); if you do not want the 50 numbers to not be repeated
      valArray.push(val);
      // if the conditional returns true,
      // create the element, style and append
      let randnum = document.createElement("p");
      randnum.classList.add('numStyle');
      randnum.style.color = randomColor();
      randnum.style.fontSize = randSize;
      randnum.textContent = val;
      randnum.style.position = 'absolute';
      randnum.style.top = `${ran[0]}px`;
      randnum.style.left = `${ran[1]}px`;
      circle.append(randnum);
      // iterate the counter
      count++;
    }
  }
}

addNumBtn.addEventListener('click', randNum)

html {
  --circle-width: 300px;
}

.circle {
  aspect-ratio: 1;
  width: var(--circleWidth);
  background-color: black;
  border-radius: 50%;
  position: relative;
  overflow: hidden;
  padding: .5rem;
}

#addNumBtn {
  position: absolute;
  top: 0;
  left: 0;
}

.numStyle {
  font-family: "roboto", sans-serif;
}

//On Clicking button Click Me! I want to place all the random numbers inside the circle //together not one by one, at a time all numbers should be placed inside the circle by //clicking the button Click Me!
<div id="container"></div>
<div class="circle">
</div>
<button id="addNumBtn">Click Me!</button>


问:
how to decide if customer is a dimension
I am creating a data warehouse (data mart) for a project-based (labor-centric) organization.  (That is, they sell labor-based "projects"; they don't sell physical products.)  They are interested in project- and customer-related dimension info.  I need to make a design decision about a certain dimension.  Should I make this dimension be "Project" (with customer info as attributes on this dimensions)?  Or, should I make two separate dimensions -- one for project and another for customer?  What are some questions to ask (or things to think about) to help me make this decision?</p>

答:
If the customer and the project represent axisis for analysis you can proceed with the following design :

The customer and the project can be Slowly Changing dimensions where you decide a type from the following :

```<code>SCD Type    Summary
Type 1      Overwrite the changes
Type 2      History will be added as a new row.
</code>```

The fact table can handle measures like the cost, the number of working days...

Body:
If the customer and the project represent axisis for analysis you can proceed with the following design :

The customer and the project can be Slowly Changing dimensions where you decide a type from the following :

SCD Type    Summary
Type 1      Overwrite the changes
Type 2      History will be added as a new row.

The fact table can handle measures like the cost, the number of working days...


问:
Pointer to base virtual function vs direct call of base virtual function
Why do these two behave differently?

```<code>(obj.*lpfn)();
</code>```

vs

```<code>obj.Base::fn();
</code>```

I know when we directly call virtual member function (obj.fn()) it will do a virtual dispatch(find correct 'fn' implementation for type of obj, and call it). But why does a pointer to member function call that is set to Base implementation((obj.*lpfn)()) lead to virtual dispatch, and why does the same expression, except directly called (obj.Base::fn()) not do virtual dispatch? If anything, I would expect them both to do call base implementation of Print function(no virtualization)

```<code>#include <iostream>
class Base {
public:
    virtual void Print() { std::cout << "Base::Print();\n"; }
};
class Derived : public Base {
public:
    void Print() override { std::cout << "Derived::Print();\n"; }
};
int main() {
    Derived d;
    auto lpfn = &Base::Print;
    (d.*lpfn)();
    d.Base::Print();
}
</code>```

Output:

```<code>Derived::Print();
Base::Print();
</code>```

答:
From the C++ standard:

[expr.call]/1 For a call to a non-static member function, the postfix expression shall be an implicit (12.2.2, 12.2.3) or explicit class member access (8.2.5) whose id-expression is a function member name, or a pointer-to-member expression (8.5) selecting a function member; the call is as a member of the class object referred to by the object expression... If the selected function is non-virtual, or if the id-expression in the class member access expression is a qualified-id, that function is called. Otherwise, its final overrider (13.3) in the dynamic type of the object expression is called; such a call is referred to as a virtual function call.

Thus, there are only two cases where virtual dispatch is not performed for a call of a non-static member function: 1) the function is not virtual to begin with, or 2) the function is named with a qualified name, as in obj.Base::fn(). In all other cases - including the case of calling via a pointer-to-member - the final overrider is called.

Body:
Why do these two behave differently?

(obj.*lpfn)();

vs

obj.Base::fn();

I know when we directly call virtual member function (obj.fn()) it will do a virtual dispatch(find correct 'fn' implementation for type of obj, and call it). But why does a pointer to member function call that is set to Base implementation((obj.*lpfn)()) lead to virtual dispatch, and why does the same expression, except directly called (obj.Base::fn()) not do virtual dispatch? If anything, I would expect them both to do call base implementation of Print function(no virtualization)

#include <iostream>
class Base {
public:
    virtual void Print() { std::cout << "Base::Print();\n"; }
};
class Derived : public Base {
public:
    void Print() override { std::cout << "Derived::Print();\n"; }
};
int main() {
    Derived d;
    auto lpfn = &Base::Print;
    (d.*lpfn)();
    d.Base::Print();
}

Output:

Derived::Print();
Base::Print();


问:
Javascript Promise Callback (when it is called)
This is a stupid question but I'm having a hard time understanding how functions are first-class citizens in javascript and when callbacks are called.

```<code>const promise = new Promise((resolve,reject) => {
    const error = false
    if(!error) {
        resolve("Promise resolved")
    } else {
        reject("Promise is rejected")
    }

})
console.log(promise) //Promise { 'Promise resolved' }
</code>```

For the code above why does the callback inside the promise (resolve, reject) => {} get called when I create a Promise? Is this something in the constructor of the Promise class? I cannot understand why it is being called immediately.

答:
The promise executor function is called immediately by the promise constructor.  That's how it works.  The usual point of that executor function is to initiate your asynchronous operation and then later when that asynchronous operation completes, you call resolve() or reject().

Here's an example of putting the plain callback version of fs.readFile() in a promise wrapper:

```<code>function readFilePromise(filename, options) {
    return new Promise((resolve, reject) => {
        fs.readFile(filename, options, (err, data) => {
            if (err) {
                reject(err);
            } else {
                resolve(data);
            }
        })
    });
}
</code>```

Usage:

```<code> readFilePromise("myfile.txt").then(data => {
     console.log(data);
 }).catch(err => {
     console.log(err);
 });
</code>```

Note: This is just an example for illustration here.  Nodejs now already has promisified versions of fs.readFile called fs.promises.readfile, but this structure can be used when you need to manually promisify other more complicated things that don't have their own promise interface yet.

For a real world example of promisifying something more complicated see the mapConcurrent() function here or the rateLimitMap() function here.

Body:
This is a stupid question but I'm having a hard time understanding how functions are first-class citizens in javascript and when callbacks are called.

const promise = new Promise((resolve,reject) => {
    const error = false
    if(!error) {
        resolve("Promise resolved")
    } else {
        reject("Promise is rejected")
    }

})
console.log(promise) //Promise { 'Promise resolved' }

For the code above why does the callback inside the promise (resolve, reject) => {} get called when I create a Promise? Is this something in the constructor of the Promise class? I cannot understand why it is being called immediately.

Body:
The promise executor function is called immediately by the promise constructor.  That's how it works.  The usual point of that executor function is to initiate your asynchronous operation and then later when that asynchronous operation completes, you call resolve() or reject().

Here's an example of putting the plain callback version of fs.readFile() in a promise wrapper:

function readFilePromise(filename, options) {
    return new Promise((resolve, reject) => {
        fs.readFile(filename, options, (err, data) => {
            if (err) {
                reject(err);
            } else {
                resolve(data);
            }
        })
    });
}

Usage:

 readFilePromise("myfile.txt").then(data => {
     console.log(data);
 }).catch(err => {
     console.log(err);
 });

Note: This is just an example for illustration here.  Nodejs now already has promisified versions of fs.readFile called fs.promises.readfile, but this structure can be used when you need to manually promisify other more complicated things that don't have their own promise interface yet.

For a real world example of promisifying something more complicated see the mapConcurrent() function here or the rateLimitMap() function here.


问:
Typography element in material ui version 5
Hi I get this error when trying to use Typography element with material-ui-5:

export 'default' (imported as 'typography') was not found in '@mui/material/typography'

here is my code:

```<code>import React from 'react';
import Typography from '@mui/material';

export default function Create() {
  return (
    <div>
        <Typography>
            Create Page
        </Typography>
    </div>
  )
}
</code>```

答:
use this :

```<code>import {Typography} from '@mui/material';
</code>```

or

```<code>import Typography from '@mui/material/Typography';
</code>```

Body:
Hi I get this error when trying to use Typography element with material-ui-5:

export 'default' (imported as 'typography') was not found in '@mui/material/typography'

here is my code:

import React from 'react';
import Typography from '@mui/material';

export default function Create() {
  return (

        <Typography>
            Create Page
        </Typography>

  )
}

Body:
use this :

import {Typography} from '@mui/material';

or

import Typography from '@mui/material/Typography';


问:
submit button just refreshes php
```<code><form method="POST">
    <div class="form-outline form-white mb-4">
  <input type="password" name="password" class="form-control" required/>
  <label class="form-label" for="form">Pass</label>
</div>
    <button type="Submit" value="send" class="btn transparent btn-block" style="color: white;">Submit</button>
  </form>

   if (isset($_POST['submit'])) {
      $password=$_POST['password'];

      if ($password=='password') {
        header("location:ari.html");
        exit();
      }
      else
        echo "Incorrect.";
    }
</code>```

I'm beginning php currently and I'm trying to use a login method, but whenever I press my submit button my code refreshes and doesn't move onto the next page I indicated. (location:ari.html)
If I could get help on what I did wrong that would be great thanks.

答:
Take a look at this line:

<form method="POST">

What happening is that when you are submitting the form it is sending data to the same page.

In this line:

if (isset($_POST['submit']))
I found no tag with name='submit' attribute. You should put this in your submit button.

If you want to send it to another page then use the action attribute in form tag and point your data to that page like action=yourpage.php

Title: submit button just refreshes php

Body:
<form method="POST">

  <input type="password" name="password" class="form-control" required/>
  Pass

    <button type="Submit" value="send" class="btn transparent btn-block" style="color: white;">Submit</button>
  </form>

   if (isset($_POST['submit'])) {
      $password=$_POST['password'];

      if ($password=='password') {
        header("location:ari.html");
        exit();
      }
      else
        echo "Incorrect.";
    }

I'm beginning php currently and I'm trying to use a login method, but whenever I press my submit button my code refreshes and doesn't move onto the next page I indicated. (location:ari.html)
If I could get help on what I did wrong that would be great thanks.


问:
How to detect contrast index of a photo?
I'm trying to take a group of photos (with the addition that more photos can be added after), and try to find a contrast/brightness/saturation index that I can use to sort the photos. Brightness and saturation is pretty easy, but I'm stuck with finding the contrast. I've tried several things (average of difference of all pixels with their neighbors, or splitting into 16 zones (4x4) and averaging difference of their averages, to fight against noise's added contrast in the previous method) but nothing gives me accurate results. My meaning of the contrast term is nothing technical/scientific, just visually high or low contrast, the one that you look by your eye and say. I am no expert of math or signal processing, and I'm looking for a simple and straightforward algorithm, if any. How do I get an overall numeric contrast index/ratio/value/whatever (as long as it can be used to sort photos) of an image?

答:
I haven't tried this, but I'd try the following steps one after another:

Noise removal. Any sort of it. Depending on how much computation you can do, I'll try either blurring (cheap), median, or a Bilateral Filter (more expensive, and possibly requires knowing the noise is more or less of the same type/effect/contrast in all the images). Note that all filters require you to know a radius which is enough to remove the noise, yet won't harm local contrast (I do hope that you have more of a global contrast than local contrast)

Create some histogram of the image brightness. Either on all the pixels, or divide it into parts (like the 16 parts you suggested above) if you want to work on a fixed size histogram.

Compute the standard deviation of the image histogram. That will be the parameter for image contrast.

ContentLicense: CC BY-SA 3.0


问:
React State not updating on key event
I'm running into an issue that I can't quite figure out. I'm building a Wordle clone, the state seems to be updating on some events and not on others, and I can't quite track down why.

I have a Keyboard component, which takes handleKeyClick as a prop from the parent component, and that is attached to two event handlers.

Parent Component

```<code>import { Box, Divider, Grid, Typography } from "@mui/material";
import { useState, useEffect, useCallback } from 'react';
import Keyboard from "../Keyboard";
import { v4 as uuid } from 'uuid'
import WordleNotifbar from "../WordleNotifBar";
import Loading from "../Utils/Loading";
import { IGuessState } from "../../types";

interface IGuessGridProps {
    addGuess: Function,
    guesses: any,
    answer: any
}
const GuessGrid = (props: IGuessGridProps) => {

    const { addGuess, guesses, answer } = props;
    let [notif, setNotif] = useState<boolean>(false);

    const [guess, setGuess] = useState<string[]>([]);
    const styles = {
        input: {
            border: ".5px solid white",
            height: "50px",
            display: "flex",
            borderRadius: "5px",
            justifyContent: "center",
            alignItems: "center",
            backgroundColor: "",
            color: "white",
        },
        container: {
            minWidth: "300px",
            width: "30%",
            maxWidth: "450px",
            margin: "0 auto",
            marginTop: "15px",
        },
    }

// In the parent component, I have defined the function I'm passing in as a prop as such:
    const handleAddCharacter = (char: string) => {
        setGuess([...guess, char])
    }

// Not fully implemented yet
    const handleBackspace = (e: MouseEvent): void => {
        e.preventDefault();
        setGuess([...guess])
    }

    const handleSubmit = (): void => {
        let word = guess.join('')
        if (word.length === answer.length) {
            addGuess(word.toLowerCase())
            setGuess([]);
        }
        else {
            setNotif(true);
            setTimeout(() => {
                setNotif(false);
            }, 1000)
        }
    }
    if (answer) {
        return <>
            <Divider />
            <Grid container sx={styles.container} >
                {answer.split('').map((_: string, index: number) => {
                    return (<Grid item xs={12 / answer.length} sx={styles.input} key={uuid()}>
                        <Box>
                            <Typography>
                                {guess[index]}
                            </Typography>
                        </Box>
                    </Grid>)
                })}
            </Grid>
            <Keyboard guesses={guesses} answer={answer} handleKeyClick={handleAddCharacter} handleBackspace={handleBackspace} submitFunc={handleSubmit} />
            {notif ? <WordleNotifbar message="Not Enough Characters" duration={1000} /> : ""}
        </>;
    } else {
        return <Loading />
    }
};

export default GuessGrid;

</code>```

Keyboard Component

```<code>import { Box, Grid, SxProps, Theme, Typography } from "@mui/material";
import { useCallback, useEffect, useState } from 'react';
import { v4 as uuid } from 'uuid';
import BackspaceIcon from '@mui/icons-material/Backspace';
import React from "react";

interface IKeyboardProps {
    guesses: string[],
    answer: string,
    handleKeyClick: any,
    submitFunc: any,
    handleBackspace: any
}
const Keyboard = (props: IKeyboardProps) => {
    const { guesses, answer, handleKeyClick, submitFunc, handleBackspace } = props
    const [guessedLetters, setGuessedLetters] = useState<string[]>();
    const topRow = 'qwertyuiop'.toUpperCase().split('');
    const middleRow = 'asdfghjkl'.toUpperCase().split('');
    const bottomRow = 'zxcvbnm'.toUpperCase().split('');
    const allKeys = topRow.concat(middleRow.concat(bottomRow));

// When the component is initialized, I am establishing an event listener in the window for the key press events.

    useEffect(() => {
        window.addEventListener('keypress', handlePhysicalKeyPress)
    }, [])

    useEffect(() => {
        const allGuessedCharacters = guesses.join('').split('');
        const uniqueGuessedCharacters = allGuessedCharacters.filter((val: string, index: number, self) => self.indexOf(val) === index)
        setGuessedLetters(uniqueGuessedCharacters);
    }, [guesses])

    const handleVirtualKeyPress = (e: any) => {
        handleKeyClick(e.target.textContent)
    }

    const handlePhysicalKeyPress = (e: KeyboardEvent) => {
        e.preventDefault()
        if (allKeys.includes(e.key.toUpperCase())) {
            handleKeyClick(e.key.toUpperCase());
        }
    }

    const genKeyStyles = (character: string, _: number): SxProps<Theme> => {
        character = character.toLowerCase()
        const styles = {
            width: character === "bs" || character === "enter" ? "63px" : "33px",
            marginX: "1px",
            marginY: "1px",
            borderRadius: "5px",
            height: "50px",
            color: "black",
            textAlign: "center",
            backgroundColor: "#DDD",
            display: "flex",
            justifyContent: "center",
            alignItems: "center",
        };
        if (guessedLetters) {
            if (answer.indexOf(character) >= 0 && guessedLetters.indexOf(character) >= 0) {
                styles.backgroundColor = "green"
            } else if (answer.indexOf(character) < 0 && guessedLetters.indexOf(character) >= 0) {
                styles.backgroundColor = "#777"
            }
        }
        return styles
    }

    return <Box sx={{ display: "flex", flexDirection: "column", justifyContent: "center", marginTop: "10px", }}>
        <Box sx={{ display: "flex", justifyContent: "center" }}>
            {topRow.map((letter: string, index: any) => {
                return (
                    <Box sx={genKeyStyles(letter, index)} key={uuid()} onClick={handleVirtualKeyPress}>
                        <Typography key={uuid()}>{letter}</Typography>
                    </Box>
                )
            })}
        </Box>
        <Box sx={{ display: "flex", justifyContent: "center" }}>
            {middleRow.map((letter: string, index: any) => {
                return (
                    <Box sx={genKeyStyles(letter, index)} key={uuid()} onClick={handleVirtualKeyPress}>
                        <Typography key={uuid()}>{letter}</Typography>
                    </Box>
                )
            })}
        </Box>
        <Box sx={{ display: "flex", justifyContent: "center" }}>
            <Box sx={genKeyStyles("enter", 1)} key={uuid()} onClick={submitFunc}>
                <Typography key={uuid()}>enter</Typography>
            </Box>

            {bottomRow.map((letter: string, index: any) => {
                return (
                    <Box sx={genKeyStyles(letter, index)} key={uuid()} onClick={handleVirtualKeyPress}>
                        <Typography key={uuid()}>{letter}</Typography>
                    </Box>
                )
            })}
            <Box sx={genKeyStyles("bs", 1)} key={uuid()} onClick={handleBackspace}>
                <Typography key={uuid()}><BackspaceIcon /></Typography>
            </Box>
        </Box>
    </Box>
};

export default Keyboard;

</code>```

What happens is that the virtual key press seems to update the state properly, but the physical keypress seems to reset the state back to an empty array. I can't really figure out a good reason why this is happening. Any thoughts? I appreciate your help in advance!

Link to Live Application

答:
When you do:

```<code>    useEffect(() => {
        window.addEventListener('keypress', handlePhysicalKeyPress)
    }, [])
</code>```

...you are attaching a specific handlePhysicalKeyPress function as event listener. But that function is re-created at each component re-render, so you no longer reference the "current" function "version" (should you try to remove it, you would not be able to because it is no longer the same reference).

As such, the actual listener is the very first "version" of your function, which calls the very first "version" of your handleKeyClick prop, which is the very first "version" of your handleAddCharacter function, which knows only the very first version of your guess state... which is an empty array.

That is why when handlePhysicalKeyPress is executed by a key press, it builds a new guess array from an empty array.

While you should avoid this discrepancy between what you attach to your event listener and your actual "render-time" function, there should be a very simple solution to your specific case: should you use the functional form of your state setter, even if it is the "very first version", it should use the "current" state version:

```<code>setGuess((currentGuess) => [...currentGuess, char])
</code>```

Title: React State not updating on key event

Body:
I'm running into an issue that I can't quite figure out. I'm building a Wordle clone, the state seems to be updating on some events and not on others, and I can't quite track down why.

I have a Keyboard component, which takes handleKeyClick as a prop from the parent component, and that is attached to two event handlers.

Parent Component

import { Box, Divider, Grid, Typography } from "@mui/material";
import { useState, useEffect, useCallback } from 'react';
import Keyboard from "../Keyboard";
import { v4 as uuid } from 'uuid'
import WordleNotifbar from "../WordleNotifBar";
import Loading from "../Utils/Loading";
import { IGuessState } from "../../types";

interface IGuessGridProps {
    addGuess: Function,
    guesses: any,
    answer: any
}
const GuessGrid = (props: IGuessGridProps) => {

    const { addGuess, guesses, answer } = props;
    let [notif, setNotif] = useState<boolean>(false);

    const [guess, setGuess] = useState<string[]>([]);
    const styles = {
        input: {
            border: ".5px solid white",
            height: "50px",
            display: "flex",
            borderRadius: "5px",
            justifyContent: "center",
            alignItems: "center",
            backgroundColor: "",
            color: "white",
        },
        container: {
            minWidth: "300px",
            width: "30%",
            maxWidth: "450px",
            margin: "0 auto",
            marginTop: "15px",
        },
    }

// In the parent component, I have defined the function I'm passing in as a prop as such:
    const handleAddCharacter = (char: string) => {
        setGuess([...guess, char])
    }

// Not fully implemented yet
    const handleBackspace = (e: MouseEvent): void => {
        e.preventDefault();
        setGuess([...guess])
    }

    const handleSubmit = (): void => {
        let word = guess.join('')
        if (word.length === answer.length) {
            addGuess(word.toLowerCase())
            setGuess([]);
        }
        else {
            setNotif(true);
            setTimeout(() => {
                setNotif(false);
            }, 1000)
        }
    }
    if (answer) {
        return <>
            <Divider />
            <Grid container sx={styles.container} >
                {answer.split('').map((_: string, index: number) => {
                    return (<Grid item xs={12 / answer.length} sx={styles.input} key={uuid()}>
                        <Box>
                            <Typography>
                                {guess[index]}
                            </Typography>
                        </Box>
                    </Grid>)
                })}
            </Grid>
            <Keyboard guesses={guesses} answer={answer} handleKeyClick={handleAddCharacter} handleBackspace={handleBackspace} submitFunc={handleSubmit} />
            {notif ? <WordleNotifbar message="Not Enough Characters" duration={1000} /> : ""}
        </>;
    } else {
        return <Loading />
    }
};

export default GuessGrid;

Keyboard Component

import { Box, Grid, SxProps, Theme, Typography } from "@mui/material";
import { useCallback, useEffect, useState } from 'react';
import { v4 as uuid } from 'uuid';
import BackspaceIcon from '@mui/icons-material/Backspace';
import React from "react";

interface IKeyboardProps {
    guesses: string[],
    answer: string,
    handleKeyClick: any,
    submitFunc: any,
    handleBackspace: any
}
const Keyboard = (props: IKeyboardProps) => {
    const { guesses, answer, handleKeyClick, submitFunc, handleBackspace } = props
    const [guessedLetters, setGuessedLetters] = useState<string[]>();
    const topRow = 'qwertyuiop'.toUpperCase().split('');
    const middleRow = 'asdfghjkl'.toUpperCase().split('');
    const bottomRow = 'zxcvbnm'.toUpperCase().split('');
    const allKeys = topRow.concat(middleRow.concat(bottomRow));

// When the component is initialized, I am establishing an event listener in the window for the key press events.

    useEffect(() => {
        window.addEventListener('keypress', handlePhysicalKeyPress)
    }, [])

    useEffect(() => {
        const allGuessedCharacters = guesses.join('').split('');
        const uniqueGuessedCharacters = allGuessedCharacters.filter((val: string, index: number, self) => self.indexOf(val) === index)
        setGuessedLetters(uniqueGuessedCharacters);
    }, [guesses])

    const handleVirtualKeyPress = (e: any) => {
        handleKeyClick(e.target.textContent)
    }

    const handlePhysicalKeyPress = (e: KeyboardEvent) => {
        e.preventDefault()
        if (allKeys.includes(e.key.toUpperCase())) {
            handleKeyClick(e.key.toUpperCase());
        }
    }

    const genKeyStyles = (character: string, _: number): SxProps<Theme> => {
        character = character.toLowerCase()
        const styles = {
            width: character === "bs" || character === "enter" ? "63px" : "33px",
            marginX: "1px",
            marginY: "1px",
            borderRadius: "5px",
            height: "50px",
            color: "black",
            textAlign: "center",
            backgroundColor: "#DDD",
            display: "flex",
            justifyContent: "center",
            alignItems: "center",
        };
        if (guessedLetters) {
            if (answer.indexOf(character) >= 0 && guessedLetters.indexOf(character) >= 0) {
                styles.backgroundColor = "green"
            } else if (answer.indexOf(character) < 0 && guessedLetters.indexOf(character) >= 0) {
                styles.backgroundColor = "#777"
            }
        }
        return styles
    }

    return <Box sx={{ display: "flex", flexDirection: "column", justifyContent: "center", marginTop: "10px", }}>
        <Box sx={{ display: "flex", justifyContent: "center" }}>
            {topRow.map((letter: string, index: any) => {
                return (
                    <Box sx={genKeyStyles(letter, index)} key={uuid()} onClick={handleVirtualKeyPress}>
                        <Typography key={uuid()}>{letter}</Typography>
                    </Box>
                )
            })}
        </Box>
        <Box sx={{ display: "flex", justifyContent: "center" }}>
            {middleRow.map((letter: string, index: any) => {
                return (
                    <Box sx={genKeyStyles(letter, index)} key={uuid()} onClick={handleVirtualKeyPress}>
                        <Typography key={uuid()}>{letter}</Typography>
                    </Box>
                )
            })}
        </Box>
        <Box sx={{ display: "flex", justifyContent: "center" }}>
            <Box sx={genKeyStyles("enter", 1)} key={uuid()} onClick={submitFunc}>
                <Typography key={uuid()}>enter</Typography>
            </Box>

            {bottomRow.map((letter: string, index: any) => {
                return (
                    <Box sx={genKeyStyles(letter, index)} key={uuid()} onClick={handleVirtualKeyPress}>
                        <Typography key={uuid()}>{letter}</Typography>
                    </Box>
                )
            })}
            <Box sx={genKeyStyles("bs", 1)} key={uuid()} onClick={handleBackspace}>
                <Typography key={uuid()}><BackspaceIcon /></Typography>
            </Box>
        </Box>
    </Box>
};

export default Keyboard;

What happens is that the virtual key press seems to update the state properly, but the physical keypress seems to reset the state back to an empty array. I can't really figure out a good reason why this is happening. Any thoughts? I appreciate your help in advance!

Link to Live Application

Body:
When you do:

    useEffect(() => {
        window.addEventListener('keypress', handlePhysicalKeyPress)
    }, [])

...you are attaching a specific handlePhysicalKeyPress function as event listener. But that function is re-created at each component re-render, so you no longer reference the "current" function "version" (should you try to remove it, you would not be able to because it is no longer the same reference).

As such, the actual listener is the very first "version" of your function, which calls the very first "version" of your handleKeyClick prop, which is the very first "version" of your handleAddCharacter function, which knows only the very first version of your guess state... which is an empty array.

That is why when handlePhysicalKeyPress is executed by a key press, it builds a new guess array from an empty array.

While you should avoid this discrepancy between what you attach to your event listener and your actual "render-time" function, there should be a very simple solution to your specific case: should you use the functional form of your state setter, even if it is the "very first version", it should use the "current" state version:

setGuess((currentGuess) => [...currentGuess, char])


问:
D3 Zoom Cannot read property 'transform' of undefined
I am trying to use a simple d3.zoom following simple tutorials as this but I always incur in the same error that I don't understand.

here is my code:

  let svg = d3.select(".chart_container")
  .append("svg")

  let g = svg.append('g')
    .attr("transform", `translate(200px, 200px)`);

  var zoom_handler = d3.zoom()
    .on("zoom", zoom_actions);

  //specify what to do when zoom event listener is triggered
  function zoom_actions(){
    g.attr("transform", d3.event.transform);
  }

  //add zoom behaviour to the svg element
  //same as svg.call(zoom_handler);
  zoom_handler(g);
```
<p>but I receive this error:</p>
```Uncaught TypeError: Cannot read property 'transform' of undefined
```

is d3.event changed? or am I doing something wrong?

答:
The following worked for me in d3 version 7.3.0</p>
```<code> .call(d3.zoom().on("zoom", function () {
    svg.attr("transform", d3.zoomTransform(this))
  }))
</code>```

Body:
I am trying to use a simple d3.zoom following simple tutorials as this but I always incur in the same error that I don't understand.

here is my code:

  let svg = d3.select(".chart_container")
  .append("svg")

  let g = svg.append('g')
    .attr("transform", `translate(200px, 200px)`);

  var zoom_handler = d3.zoom()
    .on("zoom", zoom_actions);

  //specify what to do when zoom event listener is triggered
  function zoom_actions(){
    g.attr("transform", d3.event.transform);
  }

  //add zoom behaviour to the svg element
  //same as svg.call(zoom_handler);
  zoom_handler(g);

but I receive this error:

Uncaught TypeError: Cannot read property 'transform' of undefined

is d3.event changed? or am I doing something wrong?

Body:
The following worked for me in d3 version 7.3.0

 .call(d3.zoom().on("zoom", function () {
    svg.attr("transform", d3.zoomTransform(this))
  }))


问:
How to address type errors when removing data with chart.js?
I'm using chart.js to make a simple chart. No problem producing the chart, but now I've added a remove data function per the documentation but I'm getting a type error. I assume it's because I'm incorrectly accessing the data

The error is as follows, and I'll link a JS fiddle file so you can see everything without me dumping in a wall of text.

"main.js:49 Uncaught TypeError: Cannot read properties of undefined (reading 'labels')"

My understanding is that this error tends to pop up due to scope issues, but I've defined the data globally so the function should be able to access it. I also thought that I was maybe accessing it wrong since it has a few nested arrays, so I tried btn.onclick = removeData(chart[0]); to access the first item in the chart object (the data variable) but that produced a similar error as above, but swapped in 'data' for 'labels'. Thanks for any help/input!

JSFiddle of chart

答:
First you didn't put the chart in a variable so you had no way of doing things with it. Second part, you didnt pass the function to the onclick but executed it and putted the result in the onClick.

The way it is described in the docs only works if you pass a chart variable to the function and dont do it with a button.

Also you are using a verry outdated version of chart.js with syntax for the latest. You either need to update your version or use the V2 docs

var data = {
  labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"],
  datasets: [
    {
      label: "Dataset #1",
      backgroundColor: "rgba(255,99,132,0.2)",
      borderColor: "rgba(255,99,132,1)",
      borderWidth: 2,
      hoverBackgroundColor: "rgba(255,99,132,0.4)",
      hoverBorderColor: "rgba(255,99,132,1)",
      data: [65, 59, 20, 81, 56, 55, 40],
    },
  ],
};

var options = {
  maintainAspectRatio: false,
};

const chart = new Chart("chart", {
  type: "pie",
  options: options,
  data: data,
});

function removeData() {
  chart.data.labels.pop();
  chart.data.datasets.forEach((dataset) => {
    dataset.data.pop();
  });
  chart.update();
}

let btn = document.createElement("button");
btn.innerHTML = "Remove data";
btn.onclick = removeData;
document.body.appendChild(btn);```
<pre class="snippet-code-css lang-css prettyprint-override"><code>body {
  background: #1d1f20;
  padding: 16px;
}

canvas {
  border: 1px dotted red;
}

.chart-container {
  position: relative;
  margin: auto;
  height: 80vh;
  width: 80vw;
}</code>```

<!DOCTYPE html>

  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Chart.js tutorial</title>
  <link rel="stylesheet" href="style.css" />

    <canvas id="chart"></canvas>

```

Body:
First you didn't put the chart in a variable so you had no way of doing things with it. Second part, you didnt pass the function to the onclick but executed it and putted the result in the onClick.

The way it is described in the docs only works if you pass a chart variable to the function and dont do it with a button.

Also you are using a verry outdated version of chart.js with syntax for the latest. You either need to update your version or use the V2 docs

var data = {
  labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"],
  datasets: [
    {
      label: "Dataset #1",
      backgroundColor: "rgba(255,99,132,0.2)",
      borderColor: "rgba(255,99,132,1)",
      borderWidth: 2,
      hoverBackgroundColor: "rgba(255,99,132,0.4)",
      hoverBorderColor: "rgba(255,99,132,1)",
      data: [65, 59, 20, 81, 56, 55, 40],
    },
  ],
};

var options = {
  maintainAspectRatio: false,
};

const chart = new Chart("chart", {
  type: "pie",
  options: options,
  data: data,
});

function removeData() {
  chart.data.labels.pop();
  chart.data.datasets.forEach((dataset) => {
    dataset.data.pop();
  });
  chart.update();
}

let btn = document.createElement("button");
btn.innerHTML = "Remove data";
btn.onclick = removeData;
document.body.appendChild(btn);

body {
  background: #1d1f20;
  padding: 16px;
}

canvas {
  border: 1px dotted red;
}

.chart-container {
  position: relative;
  margin: auto;
  height: 80vh;
  width: 80vw;
}

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Chart.js tutorial</title>
  <link rel="stylesheet" href="style.css" />
</head>

<body>
  <div class="chart-container">
    <canvas id="chart"></canvas>
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
</body>

</html>


问:
Remote object handles in Protocol Buffers?
Does Protocol Buffers support remote object handles? Say to support an API like the following:

```<code>service RemoteObjectsDemo {
    rpc AllocateRemoteObject() returns (RemoteObjectHandle);
    rpc UseRemoteObject(RemoteObjectHandle) returns (something);
    rpc FreeRemoteObject(RemoteObjectHandle) returns (Empty);
}
</code>```

The point is that sometimes all you need is for some object to exist on the server, but there's not need to ever transfer that object across the wire.

答:
If you were to return some database ID, then make another call and pass in the same ID to interact in more ways with the same data, that would work. You'd just lookup some state and continue where you left off. Generally, even if you load balance the application would be connecting to the same database.

You might be able to stay interactive with the same service by doing a stream of responses, which would look like this:

```<code>rpc DoSomething(SomeRequest) returns (stream ManyResponses);
</code>```

Or do bi-directional streaming.

```<code>rpc FindMax(stream FindMaxRequest) returns (stream FindMaxResponse) {};
</code>```

You'd need to come up with the rules of how many messages sent cause how many responses. Plus knowing when you'd want it all the end. Like in the above you can send values in one after the other, then whenever a new max is detected send back a response. When you ran out of values to send you'd do requestObserver.onComplete(). Then wait for all responses which would be indicated by and onComplete() event in the StreamObserver, perhaps with a latch to sync up response and sender.

Body:
Does Protocol Buffers support remote object handles? Say to support an API like the following:

service RemoteObjectsDemo {
    rpc AllocateRemoteObject() returns (RemoteObjectHandle);
    rpc UseRemoteObject(RemoteObjectHandle) returns (something);
    rpc FreeRemoteObject(RemoteObjectHandle) returns (Empty);
}

The point is that sometimes all you need is for some object to exist on the server, but there's not need to ever transfer that object across the wire.

Body:
If you were to return some database ID, then make another call and pass in the same ID to interact in more ways with the same data, that would work. You'd just lookup some state and continue where you left off. Generally, even if you load balance the application would be connecting to the same database.

You might be able to stay interactive with the same service by doing a stream of responses, which would look like this:

rpc DoSomething(SomeRequest) returns (stream ManyResponses);

Or do bi-directional streaming.

rpc FindMax(stream FindMaxRequest) returns (stream FindMaxResponse) {};

You'd need to come up with the rules of how many messages sent cause how many responses. Plus knowing when you'd want it all the end. Like in the above you can send values in one after the other, then whenever a new max is detected send back a response. When you ran out of values to send you'd do requestObserver.onComplete(). Then wait for all responses which would be indicated by and onComplete() event in the StreamObserver, perhaps with a latch to sync up response and sender.


问:
Controller calling DAO bypassing Service
In a canonical Spring MVC implementation, the architecture goes something like this

```<code>+--controller
| |
| +--MyController (@Controller, calling MyService)
|
+--service
| |
| +--MyService (interface)
| +--MyServiceImpl (@Service, calls MyDAO)
|
+--dao
| |
| +--MyDAO (interface)
| +--MyDAOImpl (@Repository, MyEntity CRUD)
|
+--entity
  |
  +--MyEntity (@Entity, corresponding to my_table in DB)
</code>```

My question is simple: What does the use of the @Service contribute to the call hierarchy? Most service classes I've seen simply encapsulate methods from the DAO.

E.g.:

```<code>@Transactional
public List<Entity> getEntities() {
    return entityDAO.getEntities();
}

@Transactional
public void saveEntity(Entity val) {
    entityDAO.saveEntity(val);
}
</code>```

Why not just bypass it and call the DAO directly from the @Controller?

RELATED: Is it bad practice that a controller calls a repository instead of a service? (formulated more abstractly outside any framework)

答:
While it's true that most service classes essentially call the DAO classes, you would want to create this structure because the service layer is where you would have your business logic.

Say you would want to do some validation on user input, have a different database query based on the passed parameters or handle database errors by converting them to appropriate business exceptions. These are things you would typically want to have in the service layer.

Body:
In a canonical Spring MVC implementation, the architecture goes something like this

+--controller
| |
| +--MyController (@Controller, calling MyService)
|
+--service
| |
| +--MyService (interface)
| +--MyServiceImpl (@Service, calls MyDAO)
|
+--dao
| |
| +--MyDAO (interface)
| +--MyDAOImpl (@Repository, MyEntity CRUD)
|
+--entity
  |
  +--MyEntity (@Entity, corresponding to my_table in DB)

My question is simple: What does the use of the @Service contribute to the call hierarchy? Most service classes I've seen simply encapsulate methods from the DAO.

E.g.:

@Transactional
public List<Entity> getEntities() {
    return entityDAO.getEntities();
}

@Transactional
public void saveEntity(Entity val) {
    entityDAO.saveEntity(val);
}

Why not just bypass it and call the DAO directly from the @Controller?

RELATED: Is it bad practice that a controller calls a repository instead of a service? (formulated more abstractly outside any framework)


问:
hide Top and Bottom Navigator on a specific screen inside Scaffold Jetpack Compose
I'm creating a simple app with bottom navigation and drawer.

I wrap all screens inside a Scaffold with topbar and bottom bar.
I want to hide top bar and bottom bar on a specific screen. Does anyone know to how achieve that

here is the code for setting up navigation.

```<code>val navController = rememberNavController()
val scaffoldState = rememberScaffoldState(rememberDrawerState(DrawerValue.Closed))

Scaffold(
    bottomBar = {
        AppBottomBar(navController)
    },
    topBar = {
        AppTopBar(scaffoldState)
    },
    drawerContent = {
        DrawerContent(navController, scaffoldState)
    },
    scaffoldState = scaffoldState
) {
    // ovoid bottom bar overlay content
    Column(modifier = Modifier.padding(bottom = 58.dp)) {
        AppNavigation(navController)
    }
}
</code>```

AppNavigation contains NavHost for navigating to screens

答:
I recommend you use AnimatedVisibility for BottomNavigation widget and TopAppBar widget, im my opinion it's clearest way for compose.

You should use remeberSaveable to store state of BottomBar and TopAppBar:

```<code>// State of bottomBar, set state to false, if current page route is "car_details"
val bottomBarState = rememberSaveable { (mutableStateOf(true)) }

// State of topBar, set state to false, if current page route is "car_details"
val topBarState = rememberSaveable { (mutableStateOf(true)) }
</code>```

In composable function we used when for control state of BottomBar and TopAppBar, below we set bottomBarState and topBarState to true, if we would like to show BottomBar and TopAppBar, otherwise we set bottomBarState and topBarState to false:

```<code>val navController = rememberNavController()

// Subscribe to navBackStackEntry, required to get current route
val navBackStackEntry by navController.currentBackStackEntryAsState()

// Control TopBar and BottomBar
when (navBackStackEntry?.destination?.route) {
    "cars" -> {
        // Show BottomBar and TopBar
        bottomBarState.value = true
        topBarState.value = true
    }
    "bikes" -> {
        // Show BottomBar and TopBar
        bottomBarState.value = true
        topBarState.value = true
    }
    "settings" -> {
        // Show BottomBar and TopBar
        bottomBarState.value = true
        topBarState.value = true
    }
    "car_details" -> {
        // Hide BottomBar and TopBar
        bottomBarState.value = false
        topBarState.value = false
    }
}

com.google.accompanist.insets.ui.Scaffold(
    bottomBar = {
        BottomBar(
            navController = navController,
            bottomBarState = bottomBarState
        )
    },
    topBar = {
        TopBar(
            navController = navController,
            topBarState = topBarState
        )
    },
    content = {
        NavHost(
            navController = navController,
            startDestination = NavigationItem.Cars.route,
        ) {
            composable(NavigationItem.Cars.route) {
                CarsScreen(
                    navController = navController,
                )
            }
            composable(NavigationItem.Bikes.route) {
                BikesScreen(
                    navController = navController
                )
            }
            composable(NavigationItem.Settings.route) {
                SettingsScreen(
                    navController = navController,
                )
            }
            composable(NavigationItem.CarDetails.route) {
                CarDetailsScreen(
                    navController = navController,
                )
            }
        }
    }
)
</code>```

Important: Scaffold from Accompanist, initialized in build.gradle. We use Scaffold from Accompanist, because we need full control of paddings, for example in default Scaffold from Compose we can't disable padding for content from top if we have TopAppBar. In our case it's required because we have animation for TopAppBar, content should be under TopAppBar and we manually control padding for each pages. Documentation from Accompanist: https://google.github.io/accompanist/insets/.

Put BottomNavigation inside AnimatedVisibility, set visible value from bottomBarState and set enter and exit animation, in my case I use slideInVertically for enter animation and slideOutVertically for exit animation:

```<code>AnimatedVisibility(
        visible = bottomBarState.value,
        enter = slideInVertically(initialOffsetY = { it }),
        exit = slideOutVertically(targetOffsetY = { it }),
        content = {
            BottomNavigation {
                val navBackStackEntry by navController.currentBackStackEntryAsState()
                val currentRoute = navBackStackEntry?.destination?.route

                items.forEach { item ->
                    BottomNavigationItem(
                        icon = {
                            Icon(
                                painter = painterResource(id = item.icon),
                                contentDescription = item.title
                            )
                        },
                        label = { Text(text = item.title) },
                        selected = currentRoute == item.route,
                        onClick = {
                            navController.navigate(item.route) {
                                popUpTo(navController.graph.findStartDestination().id) {
                                    saveState = true
                                }
                                launchSingleTop = true
                                restoreState = true
                            }
                        }
                    )
                }
            }
        }
    )
</code>```

Put TopAppBar inside AnimatedVisibility, set visible value from topBarState and set enter and exit animation, in my case I use slideInVertically for enter animation and slideOutVertically for exit animation:

```<code>AnimatedVisibility(
        visible = topBarState.value,
        enter = slideInVertically(initialOffsetY = { -it }),
        exit = slideOutVertically(targetOffsetY = { -it }),
        content = {
            TopAppBar(
                title = { Text(text = title) },
            )
        }
    )
</code>```

Full code of MainActivity:

```<code>package codes.andreirozov.bottombaranimation

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.res.painterResource
import androidx.navigation.NavController
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import codes.andreirozov.bottombaranimation.screens.BikesScreen
import codes.andreirozov.bottombaranimation.screens.CarDetailsScreen
import codes.andreirozov.bottombaranimation.screens.CarsScreen
import codes.andreirozov.bottombaranimation.screens.SettingsScreen
import codes.andreirozov.bottombaranimation.ui.theme.BottomBarAnimationTheme

@ExperimentalAnimationApi
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            BottomBarAnimationApp()
        }
    }
}

@ExperimentalAnimationApi
@Composable
fun BottomBarAnimationApp() {

    // State of bottomBar, set state to false, if current page route is "car_details"
    val bottomBarState = rememberSaveable { (mutableStateOf(true)) }

    // State of topBar, set state to false, if current page route is "car_details"
    val topBarState = rememberSaveable { (mutableStateOf(true)) }

    BottomBarAnimationTheme {
        val navController = rememberNavController()

        // Subscribe to navBackStackEntry, required to get current route
        val navBackStackEntry by navController.currentBackStackEntryAsState()

        // Control TopBar and BottomBar
        when (navBackStackEntry?.destination?.route) {
            "cars" -> {
                // Show BottomBar and TopBar
                bottomBarState.value = true
                topBarState.value = true
            }
            "bikes" -> {
                // Show BottomBar and TopBar
                bottomBarState.value = true
                topBarState.value = true
            }
            "settings" -> {
                // Show BottomBar and TopBar
                bottomBarState.value = true
                topBarState.value = true
            }
            "car_details" -> {
                // Hide BottomBar and TopBar
                bottomBarState.value = false
                topBarState.value = false
            }
        }

        // IMPORTANT, Scaffold from Accompanist, initialized in build.gradle.
        // We use Scaffold from Accompanist, because we need full control of paddings, for example
        // in default Scaffold from Compose we can't disable padding for content from top if we
        // have TopAppBar. In our case it's required because we have animation for TopAppBar,
        // content should be under TopAppBar and we manually control padding for each pages.
        com.google.accompanist.insets.ui.Scaffold(
            bottomBar = {
                BottomBar(
                    navController = navController,
                    bottomBarState = bottomBarState
                )
            },
            topBar = {
                TopBar(
                    navController = navController,
                    topBarState = topBarState
                )
            },
            content = {
                NavHost(
                    navController = navController,
                    startDestination = NavigationItem.Cars.route,
                ) {
                    composable(NavigationItem.Cars.route) {
                        // show BottomBar and TopBar
                        LaunchedEffect(Unit) {
                            bottomBarState.value = true
                            topBarState.value = true
                        }
                        CarsScreen(
                            navController = navController,
                        )
                    }
                    composable(NavigationItem.Bikes.route) {
                        // show BottomBar and TopBar
                        LaunchedEffect(Unit) {
                            bottomBarState.value = true
                            topBarState.value = true
                        }
                        BikesScreen(
                            navController = navController
                        )
                    }
                    composable(NavigationItem.Settings.route) {
                        // show BottomBar and TopBar
                        LaunchedEffect(Unit) {
                            bottomBarState.value = true
                            topBarState.value = true
                        }
                        SettingsScreen(
                            navController = navController,
                        )
                    }
                    composable(NavigationItem.CarDetails.route) {
                        // hide BottomBar and TopBar
                        LaunchedEffect(Unit) {
                            bottomBarState.value = false
                            topBarState.value = false
                        }
                        CarDetailsScreen(
                            navController = navController,
                        )
                    }
                }
            }
        )
    }
}

@ExperimentalAnimationApi
@Composable
fun BottomBar(navController: NavController, bottomBarState: MutableState<Boolean>) {
    val items = listOf(
        NavigationItem.Cars,
        NavigationItem.Bikes,
        NavigationItem.Settings
    )

    AnimatedVisibility(
        visible = bottomBarState.value,
        enter = slideInVertically(initialOffsetY = { it }),
        exit = slideOutVertically(targetOffsetY = { it }),
        content = {
            BottomNavigation {
                val navBackStackEntry by navController.currentBackStackEntryAsState()
                val currentRoute = navBackStackEntry?.destination?.route

                items.forEach { item ->
                    BottomNavigationItem(
                        icon = {
                            Icon(
                                painter = painterResource(id = item.icon),
                                contentDescription = item.title
                            )
                        },
                        label = { Text(text = item.title) },
                        selected = currentRoute == item.route,
                        onClick = {
                            navController.navigate(item.route) {
                                popUpTo(navController.graph.findStartDestination().id) {
                                    saveState = true
                                }
                                launchSingleTop = true
                                restoreState = true
                            }
                        }
                    )
                }
            }
        }
    )
}

@ExperimentalAnimationApi
@Composable
fun TopBar(navController: NavController, topBarState: MutableState<Boolean>) {
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    val title: String = when (navBackStackEntry?.destination?.route ?: "cars") {
        "cars" -> "Cars"
        "bikes" -> "Bikes"
        "settings" -> "Settings"
        "car_details" -> "Cars"
        else -> "Cars"
    }

    AnimatedVisibility(
        visible = topBarState.value,
        enter = slideInVertically(initialOffsetY = { -it }),
        exit = slideOutVertically(targetOffsetY = { -it }),
        content = {
            TopAppBar(
                title = { Text(text = title) },
            )
        }
    )
}
</code>```

Result:

Don't forget to use @ExperimentalAnimationApi annotation for compose functions.

Update: with Compose version 1.1.0 and above @ExperimentalAnimationApi not required.

22.02.2022 Update: I made some research, and update point 2. Now we use when for control topBarState and bottomBarState.

Full code available on gitHub:
https://github.com/AndreiRoze/BottomBarAnimation/tree/with_animated_topbar

Examples of animations available in the official documentation:
https://developer.android.com/jetpack/compose/animation

Body:
I'm creating a simple app with bottom navigation and drawer.

I wrap all screens inside a Scaffold with topbar and bottom bar.
I want to hide top bar and bottom bar on a specific screen. Does anyone know to how achieve that

here is the code for setting up navigation.

val navController = rememberNavController()
val scaffoldState = rememberScaffoldState(rememberDrawerState(DrawerValue.Closed))

Scaffold(
    bottomBar = {
        AppBottomBar(navController)
    },
    topBar = {
        AppTopBar(scaffoldState)
    },
    drawerContent = {
        DrawerContent(navController, scaffoldState)
    },
    scaffoldState = scaffoldState
) {
    // ovoid bottom bar overlay content
    Column(modifier = Modifier.padding(bottom = 58.dp)) {
        AppNavigation(navController)
    }
}

AppNavigation contains NavHost for navigating to screens

Body:
I recommend you use AnimatedVisibility for BottomNavigation widget and TopAppBar widget, im my opinion it's clearest way for compose.

You should use remeberSaveable to store state of BottomBar and TopAppBar:

// State of bottomBar, set state to false, if current page route is "car_details"
val bottomBarState = rememberSaveable { (mutableStateOf(true)) }

// State of topBar, set state to false, if current page route is "car_details"
val topBarState = rememberSaveable { (mutableStateOf(true)) }

In composable function we used when for control state of BottomBar and TopAppBar, below we set bottomBarState and topBarState to true, if we would like to show BottomBar and TopAppBar, otherwise we set bottomBarState and topBarState to false:

val navController = rememberNavController()

// Subscribe to navBackStackEntry, required to get current route
val navBackStackEntry by navController.currentBackStackEntryAsState()

// Control TopBar and BottomBar
when (navBackStackEntry?.destination?.route) {
    "cars" -> {
        // Show BottomBar and TopBar
        bottomBarState.value = true
        topBarState.value = true
    }
    "bikes" -> {
        // Show BottomBar and TopBar
        bottomBarState.value = true
        topBarState.value = true
    }
    "settings" -> {
        // Show BottomBar and TopBar
        bottomBarState.value = true
        topBarState.value = true
    }
    "car_details" -> {
        // Hide BottomBar and TopBar
        bottomBarState.value = false
        topBarState.value = false
    }
}

com.google.accompanist.insets.ui.Scaffold(
    bottomBar = {
        BottomBar(
            navController = navController,
            bottomBarState = bottomBarState
        )
    },
    topBar = {
        TopBar(
            navController = navController,
            topBarState = topBarState
        )
    },
    content = {
        NavHost(
            navController = navController,
            startDestination = NavigationItem.Cars.route,
        ) {
            composable(NavigationItem.Cars.route) {
                CarsScreen(
                    navController = navController,
                )
            }
            composable(NavigationItem.Bikes.route) {
                BikesScreen(
                    navController = navController
                )
            }
            composable(NavigationItem.Settings.route) {
                SettingsScreen(
                    navController = navController,
                )
            }
            composable(NavigationItem.CarDetails.route) {
                CarDetailsScreen(
                    navController = navController,
                )
            }
        }
    }
)

Important: Scaffold from Accompanist, initialized in build.gradle. We use Scaffold from Accompanist, because we need full control of paddings, for example in default Scaffold from Compose we can't disable padding for content from top if we have TopAppBar. In our case it's required because we have animation for TopAppBar, content should be under TopAppBar and we manually control padding for each pages. Documentation from Accompanist: https://google.github.io/accompanist/insets/.

Put BottomNavigation inside AnimatedVisibility, set visible value from bottomBarState and set enter and exit animation, in my case I use slideInVertically for enter animation and slideOutVertically for exit animation:

AnimatedVisibility(
        visible = bottomBarState.value,
        enter = slideInVertically(initialOffsetY = { it }),
        exit = slideOutVertically(targetOffsetY = { it }),
        content = {
            BottomNavigation {
                val navBackStackEntry by navController.currentBackStackEntryAsState()
                val currentRoute = navBackStackEntry?.destination?.route

                items.forEach { item ->
                    BottomNavigationItem(
                        icon = {
                            Icon(
                                painter = painterResource(id = item.icon),
                                contentDescription = item.title
                            )
                        },
                        label = { Text(text = item.title) },
                        selected = currentRoute == item.route,
                        onClick = {
                            navController.navigate(item.route) {
                                popUpTo(navController.graph.findStartDestination().id) {
                                    saveState = true
                                }
                                launchSingleTop = true
                                restoreState = true
                            }
                        }
                    )
                }
            }
        }
    )

Put TopAppBar inside AnimatedVisibility, set visible value from topBarState and set enter and exit animation, in my case I use slideInVertically for enter animation and slideOutVertically for exit animation:

AnimatedVisibility(
        visible = topBarState.value,
        enter = slideInVertically(initialOffsetY = { -it }),
        exit = slideOutVertically(targetOffsetY = { -it }),
        content = {
            TopAppBar(
                title = { Text(text = title) },
            )
        }
    )

Full code of MainActivity:

package codes.andreirozov.bottombaranimation

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.res.painterResource
import androidx.navigation.NavController
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import codes.andreirozov.bottombaranimation.screens.BikesScreen
import codes.andreirozov.bottombaranimation.screens.CarDetailsScreen
import codes.andreirozov.bottombaranimation.screens.CarsScreen
import codes.andreirozov.bottombaranimation.screens.SettingsScreen
import codes.andreirozov.bottombaranimation.ui.theme.BottomBarAnimationTheme

@ExperimentalAnimationApi
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            BottomBarAnimationApp()
        }
    }
}

@ExperimentalAnimationApi
@Composable
fun BottomBarAnimationApp() {

    // State of bottomBar, set state to false, if current page route is "car_details"
    val bottomBarState = rememberSaveable { (mutableStateOf(true)) }

    // State of topBar, set state to false, if current page route is "car_details"
    val topBarState = rememberSaveable { (mutableStateOf(true)) }

    BottomBarAnimationTheme {
        val navController = rememberNavController()

        // Subscribe to navBackStackEntry, required to get current route
        val navBackStackEntry by navController.currentBackStackEntryAsState()

        // Control TopBar and BottomBar
        when (navBackStackEntry?.destination?.route) {
            "cars" -> {
                // Show BottomBar and TopBar
                bottomBarState.value = true
                topBarState.value = true
            }
            "bikes" -> {
                // Show BottomBar and TopBar
                bottomBarState.value = true
                topBarState.value = true
            }
            "settings" -> {
                // Show BottomBar and TopBar
                bottomBarState.value = true
                topBarState.value = true
            }
            "car_details" -> {
                // Hide BottomBar and TopBar
                bottomBarState.value = false
                topBarState.value = false
            }
        }

        // IMPORTANT, Scaffold from Accompanist, initialized in build.gradle.
        // We use Scaffold from Accompanist, because we need full control of paddings, for example
        // in default Scaffold from Compose we can't disable padding for content from top if we
        // have TopAppBar. In our case it's required because we have animation for TopAppBar,
        // content should be under TopAppBar and we manually control padding for each pages.
        com.google.accompanist.insets.ui.Scaffold(
            bottomBar = {
                BottomBar(
                    navController = navController,
                    bottomBarState = bottomBarState
                )
            },
            topBar = {
                TopBar(
                    navController = navController,
                    topBarState = topBarState
                )
            },
            content = {
                NavHost(
                    navController = navController,
                    startDestination = NavigationItem.Cars.route,
                ) {
                    composable(NavigationItem.Cars.route) {
                        // show BottomBar and TopBar
                        LaunchedEffect(Unit) {
                            bottomBarState.value = true
                            topBarState.value = true
                        }
                        CarsScreen(
                            navController = navController,
                        )
                    }
                    composable(NavigationItem.Bikes.route) {
                        // show BottomBar and TopBar
                        LaunchedEffect(Unit) {
                            bottomBarState.value = true
                            topBarState.value = true
                        }
                        BikesScreen(
                            navController = navController
                        )
                    }
                    composable(NavigationItem.Settings.route) {
                        // show BottomBar and TopBar
                        LaunchedEffect(Unit) {
                            bottomBarState.value = true
                            topBarState.value = true
                        }
                        SettingsScreen(
                            navController = navController,
                        )
                    }
                    composable(NavigationItem.CarDetails.route) {
                        // hide BottomBar and TopBar
                        LaunchedEffect(Unit) {
                            bottomBarState.value = false
                            topBarState.value = false
                        }
                        CarDetailsScreen(
                            navController = navController,
                        )
                    }
                }
            }
        )
    }
}

@ExperimentalAnimationApi
@Composable
fun BottomBar(navController: NavController, bottomBarState: MutableState<Boolean>) {
    val items = listOf(
        NavigationItem.Cars,
        NavigationItem.Bikes,
        NavigationItem.Settings
    )

    AnimatedVisibility(
        visible = bottomBarState.value,
        enter = slideInVertically(initialOffsetY = { it }),
        exit = slideOutVertically(targetOffsetY = { it }),
        content = {
            BottomNavigation {
                val navBackStackEntry by navController.currentBackStackEntryAsState()
                val currentRoute = navBackStackEntry?.destination?.route

                items.forEach { item ->
                    BottomNavigationItem(
                        icon = {
                            Icon(
                                painter = painterResource(id = item.icon),
                                contentDescription = item.title
                            )
                        },
                        label = { Text(text = item.title) },
                        selected = currentRoute == item.route,
                        onClick = {
                            navController.navigate(item.route) {
                                popUpTo(navController.graph.findStartDestination().id) {
                                    saveState = true
                                }
                                launchSingleTop = true
                                restoreState = true
                            }
                        }
                    )
                }
            }
        }
    )
}

@ExperimentalAnimationApi
@Composable
fun TopBar(navController: NavController, topBarState: MutableState<Boolean>) {
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    val title: String = when (navBackStackEntry?.destination?.route ?: "cars") {
        "cars" -> "Cars"
        "bikes" -> "Bikes"
        "settings" -> "Settings"
        "car_details" -> "Cars"
        else -> "Cars"
    }

    AnimatedVisibility(
        visible = topBarState.value,
        enter = slideInVertically(initialOffsetY = { -it }),
        exit = slideOutVertically(targetOffsetY = { -it }),
        content = {
            TopAppBar(
                title = { Text(text = title) },
            )
        }
    )
}

Result:

Don't forget to use @ExperimentalAnimationApi annotation for compose functions.

Update: with Compose version 1.1.0 and above @ExperimentalAnimationApi not required.

22.02.2022 Update: I made some research, and update point 2. Now we use when for control topBarState and bottomBarState.

Full code available on gitHub:
https://github.com/AndreiRoze/BottomBarAnimation/tree/with_animated_topbar

Examples of animations available in the official documentation:
https://developer.android.com/jetpack/compose/animation