鉴于此代码:
class Foo {}
public class Test {
public Foo makeFoo(String p, String q) {
return new Foo(){
public void doSomething() {
System.out.println(p);
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
当你编译并运行时javap -c -p 'Test$1.class',你得到这个:
Compiled from "Test.java"
class Test$1 extends Foo {
final java.lang.String val$p;
final Test this$0;
Test$1(Test, java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #1 // Field this$0:LTest;
5: aload_0
6: aload_2
7: putfield #2 // Field val$p:Ljava/lang/String;
10: aload_0
11: invokespecial #3 // Method Foo."<init>":()V
14: return …Run Code Online (Sandbox Code Playgroud) I want to clean up all of my Docker images that aren't being used, directly or indirectly, by my current containers. Docker provides the docker image prune command for this, but I can't get it to remove exactly what I want. If I use that command without -a, it removes too little: it leaves behind all tagged images, even if no container uses them. If I use that command with -a, it removes too much: it removes images …
这是Haskell中定点组合器的通常定义:
fix :: (a -> a) -> a
fix f = let x = f x in x
Run Code Online (Sandbox Code Playgroud)
在https://wiki.haskell.org/Prime_numbers上,他们定义了一个不同的定点组合子:
_Y :: (t -> t) -> t
_Y g = g (_Y g) -- multistage, non-sharing, g (g (g (g ...)))
-- g (let x = g x in x) -- two g stages, sharing
Run Code Online (Sandbox Code Playgroud)
_Y是一个非共享的固定点组合器,在这里安排递归"伸缩"多级素数生产(生产者塔).
这到底是什么意思?在这种情况下,"共享"与"非共享"是什么?有_Y什么不同fix?
虽然学习Haskell,我遇到了一个挑战,找到两个函数f和g,使得f g和f . g是等价的(总,所以像f = undefined或f = (.) f不计).给定的解决方案是f并且g都等于\x -> x . x(或join (.)).
(我注意到这不是Haskell特有的;它可以用纯粹的组合逻辑表示为"find fand gsuch that f g = B f g",然后给定的解决方案将转换为f = g = W B.)
我理解为什么给定的解决方案在扩展时会起作用,但我不明白如果你不知道它会怎么找到它.这是我能走多远:
f g = f . g (给予)f g z = (f . g) z (双方的扩张)f g z = f (g z) (简化RHS)而且我不知道如何从那里开始.在尝试寻找解决方案时,我会做什么?
haskell functional-programming lambda-calculus combinatory-logic
考虑这个函数:
unsigned long f(unsigned long x) {
return x / 7;
}
Run Code Online (Sandbox Code Playgroud)
使用-O3,Clang将除法变成乘法,正如预期的那样:
f: # @f
movabs rcx, 2635249153387078803
mov rax, rdi
mul rcx
sub rdi, rdx
shr rdi
lea rax, [rdi + rdx]
shr rax, 2
ret
Run Code Online (Sandbox Code Playgroud)
除了rdx在 Clang 使用rcx. 但他们似乎都在做额外的举动。为什么不是这个呢?
f:
movabs rax, 2635249153387078803
mul rdi
sub rdi, rdx
shr rdi
lea rax, [rdi + rdx]
shr rax, 2
ret
Run Code Online (Sandbox Code Playgroud)
特别是,他们都将分子放在 中rax,但是通过将幻数放在那里,您根本不必移动分子。如果这实际上更好,我很惊讶 GCC 和 Clang 都没有这样做,因为这感觉很明显。他们的方式实际上比我的方式快吗?
递归方案是否有一个名字,就像一个变形,但是可以在运行时查看最终结果?这是一个精心设计的示例:
toPercents :: Floating a => [a] -> [a]
toPercents xs = result
where
(total, result) = foldr go (0, []) xs
go x ~(t, r) = (x + t, 100*x/total:r)
{-
>>> toPercents [1,2,3]
[16.666666666666668,33.333333333333336,50.0]
-}
Run Code Online (Sandbox Code Playgroud)
该示例total在折叠的每一步都使用,即使直到结束时才知道其值。(显然,这取决于工作的懒惰。)
给定一个Float或Double,我如何得到它的下一个更大或更小的一个?换句话说,如何执行与C ++ std::nextafter函数等效的功能?例如,给定0 :: Float,我想为1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45(其中showS作为1.0e-45)作为下一个较大的一个,并给予1 :: Float,我想为0.999999940395355224609375(其中showS作为0.99999994)作为下一个较小的一个。如果可能的话,我想知道如何在Haskell中自己完成此操作,而不是仅使用第三方库(base尽管可以解决问题)或使用FFI调用该C ++函数。
考虑以下Vect类型:
{-# LANGUAGE GADTs, DataKinds, KindSignatures, RankNTypes #-}
import Data.Kind (Type)
data Nat = Zero | Succ Nat
data Vect :: Nat -> Type -> Type where
Nil :: Vect 'Zero a
Cons :: a -> Vect n a -> Vect ('Succ n) a
Run Code Online (Sandbox Code Playgroud)
我想编写一个函数,该函数接受一个列表并将其延迟转换为这种类型。由于长度显然是未知的,因此我们需要使用一个存在的。我第一次尝试使用CPS和2级类型来模拟一个:
listToVect1 :: [a] -> (forall n. Vect n a -> b) -> b
listToVect1 [] f = f Nil
listToVect1 (x:xs) f = listToVect1 xs (f . Cons x)
Run Code Online (Sandbox Code Playgroud)
但是,这并不懒。这只是一个折叠(尽管写为显式递归,因为实际使用foldl会要求难以理解),因此f …
haskell lazy-evaluation existential-type continuation-passing dependent-type
考虑这个 GHCi 会话:
$ ghci
GHCi, version 8.6.5: http://www.haskell.org/ghc/ :? for help
Prelude> :set -Wincomplete-patterns -Wincomplete-uni-patterns
Prelude> foo t | (_, _) <- t = "Foo"
Prelude> bar t | (_, _) <- id t = "Foo"
Prelude> baz x | Just _ <- x = "Yes" | Nothing <- x = "No"
Prelude> qux x | Just _ <- id x = "Yes" | Nothing <- id x = "No"
<interactive>:3:1: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an …Run Code Online (Sandbox Code Playgroud) 考虑这些不同的尝试,例如last:
Prelude> import Data.Foldable
Prelude Data.Foldable> foldr const undefined (reverse [1,2,3])
3
Prelude Data.Foldable> foldr' const undefined (reverse [1,2,3])
3
Prelude Data.Foldable> foldl (flip const) undefined [1,2,3]
3
Prelude Data.Foldable> foldl' (flip const) undefined [1,2,3]
*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries/base/GHC/Err.hs:79:14 in base:GHC.Err
undefined, called at <interactive>:5:21 in interactive:Ghci4
Run Code Online (Sandbox Code Playgroud)
这对我来说是有道理的,foldl而且foldr两者都有效,因为它们对累加器并不严格,而对我来说不严格是有道理的foldl',因为它是。但为什么foldr'有效?它的累加器不应该也很严格吗?
haskell ×7
assembly ×1
c ×1
catamorphism ×1
clang ×1
docker ×1
fold ×1
gcc ×1
java ×1
letrec ×1
strictness ×1
x86-64 ×1
y-combinator ×1