IT練習ノート

IT関連で調べたこと(実際は嵌ったこと)を書いています。

Haskellのerrorで嵌る

次のような作りかけのコードを書いていました。errorの部分はあとで修正していくつもりでした。コーディングが進んで、errorの部分をコーディングする段階に来たのですが、show tの内容が出力されませんでした。

paramMetaData2TypeString_ (VAR   tipe len)      =
  case tipe of
    (VARLEN_BYTELEN_TYPE   t) ->
      case t of
        INTNTYPE -> case (lengthTYPE_VARLEN len) of
                        0x01 -> "tinyint"
                        0x02 -> "smallint"
                        0x04 -> "int"
                        0x08 -> "bigint"
        _          -> error  "not yet implemented. type=" ++ (show t)  -- TODO

結局errorの後に$が抜けているだけなのです。

ただ、$がなくてもタイプチェックになってしまうのが落とし穴でした。

 >
 > :t error
error :: [Char] -> a
 > error "foo"
*** Exception: foo
CallStack (from HasCallStack):
  error, called at <interactive>:25:1 in interactive:Ghci2
 > :t error "foo"
error "foo" :: a

> -- $をつけない

 > error "foo" ++ show "bar"
"*** Exception: foo
CallStack (from HasCallStack):
  error, called at <interactive>:27:1 in interactive:Ghci2
 > :t error "foo" ++ show "bar"
error "foo" ++ show "bar" :: [Char]

> -- $をつける

 > error $ "foo" ++ show "bar"
*** Exception: foo"bar"
CallStack (from HasCallStack):
  error, called at <interactive>:32:1 in interactive:Ghci2
 > :t error $ "foo" ++ show "bar"
error $ "foo" ++ show "bar" :: a
 >

Haskellの時間で嵌る

UTCTimeDay`DiffTimeから構成されます。DiffTimeはドキュメントに0 <= t < 86401sの範囲と記載されていますが、範囲以上でも動いてしまうようです。

 > y = secondsToDiffTime 60 * 60 * 24
 > z2 = UTCTime (fromGregorian 2018 11 17) y
 > z2
2018-11-17 23:59:60 UTC
 > y = secondsToDiffTime 60 * 60 * 24 + 1
 > z2 = UTCTime (fromGregorian 2018 11 17) y
 > z2
2018-11-17 23:59:61 UTC
 > y = secondsToDiffTime 60 * 60 * 24 + 100
 > z2 = UTCTime (fromGregorian 2018 11 17) y
 > z2
2018-11-17 23:59:160 UTC

Javaのlambdaやstreamのベストプラクティスは?

ラムダ式のベストプラクティス

Best Practices using Java 8 Lambdas | Baeldung

StreamAPIコーディング規約

coding-standards/Javaコーディング規約.md at 8f152d2a7c6853f14345fbd9f10a9a0b14525e1f · future-architect/coding-standards · GitHub

StreamAPIパフォーマンス注意点

coding-standards/Javaコーディング規約.md at 8f152d2a7c6853f14345fbd9f10a9a0b14525e1f · future-architect/coding-standards · GitHub

The perilously long lambda

Java 8 idioms: Why the perfect lambda expression is just one line

  • その他
    • Streamの処理では、副作用のある処理は書かない
    • Streamの処理ラムダ式は1行(ブロックを必要としない)とする。-> 2行以上(ブロックを必要とする)の時は、関数インターフェースを使う。
    • (ラムダ式内の処理は短い前提のもと)ラムダ式の変数名はx, y, z等の短い文字を使う。
    • ラムダ式は共有しない。使い捨て前提
import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        String[] list01 = {"a", "b", "c"};

        String[] ret01 = Arrays.stream(list01)
                               .map(Main::addSquareBracket)
                               .toArray(String[]::new);

        Arrays.stream(ret01).forEach(System.out::println); // debug
    }

    private static String addSquareBracket(String s) {
        return "[" + s + "]";  // 複雑な処理のつもり
    }
    
}

SQLServer Management Studioの上位200件の編集で、decimal(38,0)は扱えない模様

直接セルを入力しようとすると20桁までしか受け付けてくれません。38桁の値をSQLで設定した後にみると、<ファイルを読み取れません>となります。

update TBL_DECIMAL set x_decimal_38_0 = 99999999999999999999999999999999999999 where x_id = 13;

f:id:naotoogawa:20181028120911p:plain

SQLServerの浮動小数の仮数の指定

マニュアルをみると、float [ (n) ]と記載されているので、nを指定できるように思えます。

https://docs.microsoft.com/ja-jp/sql/t-sql/data-types/float-and-real-transact-sql?view=sql-server-2017

実際create tablefloat(14)などとしてもエラーになります。

CREATE TABLE [dbo].[TBL_foo](
    [x_float] [float(14)] NULL,
) 
メッセージ 2715、レベル 16、状態 6、行 3
列、パラメーター、または変数 #1: データ型 float(14) が見つかりません。

すぐ下の注意にあるように、n=23 か n=53 として扱われます。

On creating a table column of type "float with precision" column gets created as "real" type in SQL server - Stack Overflow

Haskellにはforがない。でもループのインデックスみたいなやつを使いたいとき。

> ['a','b','c']

のようなリストを扱っているときに、インデックスも使って処理をしたい時があるかもしれません。

その場合は自分でインデックスを付与してあげます。

 > zip [0..] ['a','b','c']
[(0,'a'),(1,'b'),(2,'c')]
 >

fold系の関数を使うときに、タプルで受け取って処理をすればよいと思います。

> foldl (\acc (idx,x)-> acc ++ (show (idx,x))) "" $ zip [0..] ['a','b','c']
"(0,'a')(1,'b')(2,'c')"
>

HaskellのshiftLではまった話

数値リテラルで計算すると期待する結果になるけど、なぜかバインドした値を使うと結果が異なり、しばらく悩みました。

 > a
10
 > b
149
 > c
91
 > a `shiftL` 16 .|. b `shiftL` 8 .|. c -- 期待していない結果
91
 > 10 `shiftL` 16 .|. 149 `shiftL` 8 .|. 91 -- これが期待する結果
693595
 >

理由は、型がWord8だからでした。左にシフトしても桁あふれてしまうので、期待した結果になりませんでした。

 > :t a
a :: Word8
 > :t b
b :: Word8
 > :t c
c :: Word8
 >

つまり

c :: Word8
 > (10::Word8) `shiftL` 16
0
 > (149::Word8) `shiftL` 8
0
 >

ということ。