IT練習ノート

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

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
 >

ということ。

重複したフィールドラベル

今の手元の環境は下記なのですが、

 > :! stack ghc -- --version
The Glorious Glasgow Haskell Compilation System, version 8.2.2

下記のブログ記事をコピペして手元で動作させたらコンパイルエラーになりました。

d.hatena.ne.jp

IsLabelクラスのfromLabel関数に、いつのタイミングなのか明確に調べていませんが、APIの変更があったようです。

base-4.9.1.0

class IsLabel (x :: Symbol) a where
  fromLabel :: Proxy# x -> a

base-4.10.1.0

class IsLabel (x :: Symbol) a where
  fromLabel :: a

Duplicate Record Fields in Haskell